// // Created by nano on 4/26/25. // #include "communication.h" #include #include #include //TODO: Add descriptive enum for the different return values //TODO: ADD DOCUMENTATION struct sp_port * port; struct sp_event_set *event_data_ready; struct sp_event_set *event_ready_for_tx; /** * Initializes the serial communication for the usb -> uart board */ void comm_init_communication() { struct sp_port **port_list; comm_get_port_list(&port_list); int portnr=0; comm_list_serial_ports(port_list); printf("Chose a port: "); scanf("%d",&portnr); sp_copy_port(port_list[portnr], &port); sp_free_port_list(port_list); comm_open_port(); } void comm_get_port_list(struct sp_port ***port_list) { enum sp_return result = sp_list_ports(port_list); if (result != SP_OK) { printf("Error listing serial ports\n"); exit(-1); } } void comm_list_serial_ports(struct sp_port **port_list) { printf("Port list:\n"); for (int i = 0; port_list[i] != NULL; i++) { char *port_name = sp_get_port_name(port_list[i]); printf("Port %d: %s\n", i, port_name); } } void comm_open_port() { /* * Opens communication to the selected serial port and sets the correct parameters for the zigbee carrier board. * Also add event to see when data arrives. */ check(sp_open(port, SP_MODE_READ_WRITE)); check(sp_set_baudrate(port, 19200)); check(sp_set_bits(port, 8)); check(sp_set_parity(port, SP_PARITY_NONE)); check(sp_set_stopbits(port, 1)); check(sp_new_event_set(&event_data_ready)); check(sp_new_event_set(&event_ready_for_tx)); sp_add_port_events(event_data_ready, port, SP_EVENT_RX_READY); sp_add_port_events(event_ready_for_tx, port, SP_EVENT_TX_READY); } /** * Ends the serial communication for the usb -> uart board */ void comm_end_communication() { check(sp_close(port)); sp_free_port(port); } int comm_await_data_ready(int timeout) { // Await data from the robot return (sp_wait(event_data_ready, timeout) == SP_OK); } int comm_await_ready_for_tx(int timeout) { return (sp_wait(event_ready_for_tx, timeout) == SP_OK); } int comm_nonblocking_read(byte *data, int amount_of_bytes) { //read available data //TODO: TEST ACTUAL READ LOGIC int recv_bytes = sp_nonblocking_read(port, data, amount_of_bytes); if (recv_bytes == amount_of_bytes) { return 1; } if (recv_bytes >= 0) { return 0; } return -1; } int comm_blocking_read(byte *data, int amount_of_bytes, int timeout) { //read available data //TODO: TEST ACTUAL READ LOGIC int recv_bytes = sp_blocking_read(port, data, amount_of_bytes, timeout); if (recv_bytes == amount_of_bytes) { return 1; } if (recv_bytes >= 0) { return 0; } return -1; } int comm_blocking_write(byte *data, int amount_of_bytes,int timeout) { // we are writing 8 bit bytes to the fpga anyways and pc -> fpga only needs to tell what do to next, can be fit in 8 bits //TODO: TEST ACTUAL WRITE LOGIC int sent_bytes = sp_blocking_write(port, data, amount_of_bytes, timeout); if (sent_bytes == amount_of_bytes) { return 1; } if (sent_bytes >= 0) { return 0; } return -1; } int comm_nonblocking_write(byte *data, int amount_of_bytes) { // we are writing 8 bit bytes to the fpga anyways and pc -> fpga only needs to tell what do to next, can be fit in 8 bits //TODO: TEST ACTUAL WRITE LOGIC int sent_bytes = sp_nonblocking_write(port, data, amount_of_bytes); if (sent_bytes == amount_of_bytes) { return 1; } if (sent_bytes >=0) { return 0; } return -1; } /** Helper function for error handling. Taken from libserialport examples */ int check(enum sp_return result) { /* For this example we'll just exit on any error by calling abort(). */ char *error_message; switch (result) { case SP_ERR_ARG: printf("Error: Invalid argument.\n"); abort(); case SP_ERR_FAIL: error_message = sp_last_error_message(); printf("Error: Failed: %s\n", error_message); sp_free_error_message(error_message); abort(); case SP_ERR_SUPP: printf("Error: Not supported.\n"); abort(); case SP_ERR_MEM: printf("Error: Couldn't allocate memory.\n"); abort(); case SP_OK: default: return result; } }