/* Note: This example requires LIN 1 and LIN 2 channels to be connected on the device */ #include #include #include #ifdef _WIN32 #include #else #include #endif #include #include void sleep_ms(uint32_t ms) { #ifdef _WIN32 Sleep(ms); #else sleep(ms / 1000); #endif } int print_error_code(const char* message, icsneoc2_error_t error) { char error_str[64]; size_t error_str_len = sizeof(error_str); icsneoc2_error_t res = icsneoc2_error_code_get(error, error_str, &error_str_len); if(res != icsneoc2_error_success) { printf("%s: Failed to get string for error code %d with error code %d\n", message, error, res); return res; } printf("%s: \"%s\" (%u)\n", message, error_str, error); return (int)error; } void print_events(const char* device_description) { icsneoc2_event_t* events[1024] = {0}; size_t events_count = 1024; for(size_t i = 0; i < events_count; ++i) { icsneoc2_error_t res = icsneoc2_event_get(&events[i], NULL); if(res != icsneoc2_error_success) { for(size_t j = 0; j < i; ++j) { icsneoc2_event_free(events[j]); } (void)print_error_code("\tFailed to get device events", res); return; } if(events[i] == NULL) { events_count = i; break; } } for(size_t i = 0; i < events_count; i++) { char event_description[255] = {0}; size_t event_description_length = 255; icsneoc2_error_t res = icsneoc2_event_description_get(events[i], event_description, &event_description_length); if(res != icsneoc2_error_success) { print_error_code("\tFailed to get event description", res); continue; } printf("\t%s: Event %zu: %s\n", device_description, i, event_description); } for(size_t i = 0; i < events_count; i++) { icsneoc2_event_free(events[i]); } printf("\t%s: Received %zu events\n", device_description, events_count); } void process_lin_messages(icsneoc2_message_t** messages, size_t count) { for(size_t i = 0; i < count; i++) { bool is_lin = false; icsneoc2_error_t res = icsneoc2_message_is_lin(messages[i], &is_lin); if(res != icsneoc2_error_success || !is_lin) continue; uint8_t id = 0; uint8_t protected_id = 0; uint8_t checksum = 0; icsneoc2_lin_msg_type_t msg_type = 0; bool is_enhanced_checksum = false; res = icsneoc2_message_lin_props_get(messages[i], &id, &protected_id, &checksum, &msg_type, &is_enhanced_checksum); if(res != icsneoc2_error_success) { print_error_code("\tFailed to get LIN properties", res); continue; } icsneoc2_netid_t netid = 0; icsneoc2_message_netid_get(messages[i], &netid); char netid_name[128] = {0}; size_t netid_name_length = 128; icsneoc2_netid_name_get(netid, netid_name, &netid_name_length); uint8_t data[64] = {0}; size_t data_length = 64; icsneoc2_message_data_get(messages[i], data, &data_length); icsneoc2_lin_err_flags_t err_flags = 0; icsneoc2_message_lin_err_flags_get(messages[i], &err_flags); printf("\t%s RX | ID: 0x%02x | Protected ID: 0x%02x\n", netid_name, id, protected_id); printf("\tData: ["); for(size_t x = 0; x < data_length; x++) { printf(" 0x%02x", data[x]); } printf(" ]\n"); printf("\tChecksum type: %s\n", is_enhanced_checksum ? "Enhanced" : "Classic"); printf("\tChecksum: 0x%02x\n", checksum); printf("\tChecksum valid: %s\n\n", (!(err_flags & ICSNEOC2_LIN_ERR_CHECKSUM_MATCH)) ? "yes" : "no"); } } int main() { /* Open the first available device */ printf("Opening first available device...\n"); icsneoc2_device_t* device = NULL; icsneoc2_error_t res = icsneoc2_device_open_first(0, icsneoc2_open_options_default, &device); if(res != icsneoc2_error_success) { return print_error_code("\tFailed to open first device", res); } char description[255] = {0}; size_t description_length = 255; res = icsneoc2_device_description_get(device, description, &description_length); if(res != icsneoc2_error_success) { icsneoc2_device_close(device); return print_error_code("\tFailed to get device description", res); } printf("\tOpened device: %s\n\n", description); /* Configure LIN settings */ int64_t baud = 19200; printf("Enable LIN 01 commander resistor... "); res = icsneoc2_settings_commander_resistor_set(device, icsneoc2_netid_lin_01, true); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); printf("Disable LIN 02 commander resistor... "); res = icsneoc2_settings_commander_resistor_set(device, icsneoc2_netid_lin_02, false); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); printf("Setting LIN 01 baudrate to %" PRId64 " bit/s... ", baud); res = icsneoc2_settings_baudrate_set(device, icsneoc2_netid_lin_01, baud); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); printf("Setting LIN 02 baudrate to %" PRId64 " bit/s... ", baud); res = icsneoc2_settings_baudrate_set(device, icsneoc2_netid_lin_02, baud); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); printf("Setting LIN 01 mode to NORMAL... "); res = icsneoc2_settings_lin_mode_set(device, icsneoc2_netid_lin_01, icsneoc2_lin_mode_normal); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); printf("Setting LIN 02 mode to NORMAL... "); res = icsneoc2_settings_lin_mode_set(device, icsneoc2_netid_lin_02, icsneoc2_lin_mode_normal); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); printf("Applying settings... "); res = icsneoc2_settings_apply(device); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to apply settings", res); } printf("OK\n"); printf("Getting LIN 01 baudrate... "); int64_t read_baud = 0; res = icsneoc2_settings_baudrate_get(device, icsneoc2_netid_lin_01, &read_baud); if(res == icsneoc2_error_success) printf("OK, %" PRId64 " bit/s\n", read_baud); else printf("FAIL\n"); printf("Getting LIN 02 baudrate... "); res = icsneoc2_settings_baudrate_get(device, icsneoc2_netid_lin_02, &read_baud); if(res == icsneoc2_error_success) printf("OK, %" PRId64 " bit/s\n\n", read_baud); else printf("FAIL\n\n"); /* Transmit a LIN responder data update on LIN 02 */ printf("Transmitting a LIN 02 responder data frame... "); { icsneoc2_message_t* msg = NULL; res = icsneoc2_message_lin_create(&msg, 0x11); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to create LIN message", res); } icsneoc2_lin_msg_type_t msg_type = icsneoc2_lin_msg_type_update_responder; res = icsneoc2_message_lin_props_set(msg, NULL, NULL, &msg_type, NULL); uint8_t data[] = {0xaa, 0xbb, 0xcc, 0xdd, 0x11, 0x22, 0x33, 0x44}; res += icsneoc2_message_data_set(msg, data, sizeof(data)); res += icsneoc2_message_netid_set(msg, icsneoc2_netid_lin_02); res += icsneoc2_message_lin_calc_checksum(msg); if(res != icsneoc2_error_success) { icsneoc2_message_free(msg); print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to set LIN message properties", res); } res = icsneoc2_device_message_transmit(device, msg); icsneoc2_message_free(msg); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to transmit LIN responder message", res); } printf("OK\n"); } /* Transmit a LIN commander header on LIN 01 */ printf("Transmitting a LIN 01 commander header... "); { icsneoc2_message_t* msg = NULL; res = icsneoc2_message_lin_create(&msg, 0x11); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to create LIN message", res); } icsneoc2_lin_msg_type_t msg_type = icsneoc2_lin_msg_type_header_only; res = icsneoc2_message_lin_props_set(msg, NULL, NULL, &msg_type, NULL); res += icsneoc2_message_netid_set(msg, icsneoc2_netid_lin_01); if(res != icsneoc2_error_success) { icsneoc2_message_free(msg); print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to set LIN message properties", res); } res = icsneoc2_device_message_transmit(device, msg); icsneoc2_message_free(msg); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to transmit LIN header", res); } printf("OK\n\n"); } sleep_ms(100); /* Transmit a LIN commander message with data on LIN 01 */ printf("Transmitting a LIN 01 commander frame with data... "); { icsneoc2_message_t* msg = NULL; res = icsneoc2_message_lin_create(&msg, 0x22); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to create LIN message", res); } icsneoc2_lin_msg_type_t msg_type = icsneoc2_lin_msg_type_commander_msg; bool enhanced = true; res = icsneoc2_message_lin_props_set(msg, NULL, NULL, &msg_type, &enhanced); uint8_t data[] = {0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb, 0xcc, 0xdd}; res += icsneoc2_message_data_set(msg, data, sizeof(data)); res += icsneoc2_message_netid_set(msg, icsneoc2_netid_lin_01); res += icsneoc2_message_lin_calc_checksum(msg); if(res != icsneoc2_error_success) { icsneoc2_message_free(msg); print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to set LIN message properties", res); } res = icsneoc2_device_message_transmit(device, msg); icsneoc2_message_free(msg); if(res != icsneoc2_error_success) { print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to transmit LIN commander message", res); } printf("OK\n\n"); } sleep_ms(100); /* Read back any received messages and display LIN frames */ icsneoc2_message_t* messages[2048] = {0}; size_t message_count = 2048; printf("Getting messages...\n"); for(size_t i = 0; i < message_count; ++i) { res = icsneoc2_device_message_get(device, &messages[i], 0); if(res != icsneoc2_error_success) { for(size_t j = 0; j < i; ++j) { icsneoc2_message_free(messages[j]); } print_events(description); icsneoc2_device_close(device); return print_error_code("\tFailed to get messages", res); } if(messages[i] == NULL) { message_count = i; break; } } printf("\tReceived %zu messages\n", message_count); process_lin_messages(messages, message_count); for(size_t i = 0; i < message_count; ++i) { icsneoc2_message_free(messages[i]); } /* Cleanup */ print_events(description); printf("Closing device... "); res = icsneoc2_device_close(device); printf("%s\n", res == icsneoc2_error_success ? "OK" : "FAIL"); return 0; }