From dbca9b0d10cbdbbad02ef16f97c11816ea5a42f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicholas=20St=C4=83nescu?= Date: Sat, 26 Apr 2025 22:52:42 +0200 Subject: [PATCH] some refactoring, a little more code and a bit of documentation --- CMakeLists.txt | 2 + communication.c | 51 ++++++------- communication.h | 15 +++- docs/readme.md | 199 ++++++++++++++++++++++++++++++++++++++++++++++++ main.c | 45 +++++------ utils.c | 23 ++++++ utils.h | 13 ++++ 7 files changed, 293 insertions(+), 55 deletions(-) create mode 100644 docs/readme.md create mode 100644 utils.c create mode 100644 utils.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a7ee9d..ea89309 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ include_directories(.) add_executable(serial communication.c communication.h + utils.c + utils.h main.c) target_link_libraries(serial serialport) diff --git a/communication.c b/communication.c index 602d7da..c636a02 100644 --- a/communication.c +++ b/communication.c @@ -8,9 +8,10 @@ #include #include + struct sp_port ** port_list; struct sp_port * port; - +struct sp_event_set *event_set; void comm_init_communication() { /* @@ -21,29 +22,39 @@ void comm_init_communication() { comm_list_serial_ports(port_list); printf("Chose a port: "); scanf("%d",&portnr); - port=port_list[portnr]; + sp_copy_port(port_list[portnr], &port); + sp_free_port_list(port_list); comm_open_port(port); } + void comm_end_communication(struct sp_port *port) { /* * Ends the serial communication for the usb -> uart board */ check(sp_close(port)); - sp_free_port_list(port_list); + sp_free_port(port); + //sp_free_port_list(port_list); } -int comm_write(byte data) { +int comm_await() { + // Await data from the robot + return (sp_wait(event_set, 50) == SP_OK); +} + +int comm_read_byte(byte *data) { + //read available data + //TODO: IMPLEMENT + return 0; +} + + +int comm_write_byte(byte data) { // 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: IMPLEMENT return 0; } -int comm_await() { - // Await data from the robot - //TODO: IMPLEMENT - return 0; -} struct sp_port **comm_get_port_list() { struct sp_port **port_list; @@ -66,15 +77,19 @@ void comm_list_serial_ports(struct sp_port **port_list) { void comm_open_port(struct sp_port *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_set)); + sp_add_port_events(event_set, port, SP_EVENT_RX_READY); } -/* Helper function for error handling. Taken from libserialport examples */ +/** 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(). */ @@ -100,19 +115,3 @@ int check(enum sp_return result) return result; } } - -void uint8_to_bit_array(byte bit_array[], byte data) { - for (int i = 0; i < 8; i++) { - bit_array[i] = (data >> i) & 1; - } -} - -byte bit_array_to_uint8(byte bit_array[]) { - byte data=0; - byte currentpow=1; - for (int i = 0; i < 8; i++) { - data+=bit_array[i]*currentpow; - currentpow*=2; - } - return data; -} diff --git a/communication.h b/communication.h index 7f617b4..f533de3 100644 --- a/communication.h +++ b/communication.h @@ -9,10 +9,13 @@ typedef u_int8_t byte; +/** + * Initializes the serial communication for the usb -> uart board + */ void comm_init_communication(); /** - * Initializes the serial communication for the usb -> uart board + * Ends the serial communication for the usb -> uart board */ void comm_end_communication(struct sp_port *port); @@ -20,10 +23,16 @@ struct sp_port **comm_get_port_list(); void comm_list_serial_ports(struct sp_port **port_list); +/** + * Opens communication to the selected serial port and sets the correct parameters for the zigbee carrier board. + */ void comm_open_port(struct sp_port *port); + +int comm_await(); + + int check(enum sp_return result); -void uint8_to_bit_array(byte *bit_array, byte data); -byte bit_array_to_uint8(const byte bit_array[]); + #endif //COMMS_H diff --git a/docs/readme.md b/docs/readme.md new file mode 100644 index 0000000..bbe65df --- /dev/null +++ b/docs/readme.md @@ -0,0 +1,199 @@ +# Serial Communication Module Documentation + +## Overview + +This module provides serial communication functionality using `libserialport` to interface with USB/UART devices. It +handles port enumeration, configuration, and basic I/O operations. + +--- + +## Data Structures + +### `sp_port` + +`struct sp_port` +Represents a serial port (opaque type from libserialport). + +### `sp_port_list` + +`struct sp_port **` +Linked list of available serial ports. + +### `sp_event_set` + +`struct sp_event_set *` +Event monitoring structure for asynchronous I/O. + +--- + +## Core Functions + +### Initialization & Cleanup + +```c +void comm_init_communication() +``` + +- **Purpose**: Initialize serial communication +- **Workflow**: + 1. Lists available ports + 2. Prompts user for port selection + 3. Configures port parameters (19200 baud, 8N1) + 4. Sets up RX event monitoring +- **Note**: Must be called first + +```c +void comm_end_communication(struct sp_port *port) +``` + +- **Purpose**: Clean up communication resources +- **Parameters**: + - `port`: Active port to close +- **Effects**: + - Closes port connection + - Releases port memory + +--- + +### Port Management + +```c +struct sp_port **comm_get_port_list() +``` + +- **Returns**: Linked list of available serial ports +- **Failure**: Exits program on error + +```c +void comm_list_serial_ports(struct sp_port **port_list) +``` + +- **Purpose**: Display available ports +- **Output Format**: + +Port 0: /dev/ttyUSB0 +Port 1: /dev/ttyACM0 + +```c +void comm_open_port(struct sp_port *port) +``` + +- **Purpose**: Configure port parameters +- **Settings Applied**: + - Baudrate: 19200 + - Data Bits: 8 + - Parity: None + - Stop Bits: 1 + - Event: RX Ready monitoring + +--- + +### I/O Operations + +```c +int comm_await() +``` + +- **Purpose**: Check for incoming data +- **Returns**: + - `1`: Data available + - `0`: No data/timeout +- **Timeout**: 50ms + +```c +int comm_read_byte(byte *data) +``` + +- **Purpose**: Read single byte (UNIMPLEMENTED) +- **TODO**: Implement actual read logic +- **Returns**: Placeholder (0) + +```c +int comm_write_byte(byte data) +``` + +- **Purpose**: Write single byte (UNIMPLEMENTED) +- **TODO**: Implement actual write logic +- **Returns**: Placeholder (0) + +--- + +## Helper Function + +```c +int check(enum sp_return result) +``` + +- **Error Handling**: Converts libserialport error codes to human-readable messages +- **Failure Modes**: + - Invalid arguments + - Operation failure + - Unsupported features + - Memory allocation errors +- **Behavior**: Aborts program on error + +--- + +## Usage Example + +```c +int main() { +comm_init_communication(); + + while(1) { + if(comm_await()) { + byte data; + if(comm_read_byte(&data)) { + // Process data + } + } + + // comm_write_byte(0x55); + } + + comm_end_communication(port); + return 0; +} +``` + +--- + +## Dependencies + +- **libserialport**: Required for low-level serial operations +- **stdio.h**: For I/O operations +- **stdlib.h**: For memory management + +--- + +## Error Handling + +The module uses aggressive error handling through the `check()` helper: + +- **Critical Errors**: Program termination via `abort()` +- **Error Types**: + - Invalid arguments + - Hardware failures + - Unsupported operations + - Memory issues + +--- + +## Implementation Notes + +1. **Port Selection**: Current implementation uses console input +2. **Baudrate**: Fixed at 19200 (modify in `comm_open_port()`) +3. **Thread Safety**: Not thread-safe in current implementation +4. **Event Handling**: Only monitors RX events currently + +--- + +## TODO List + +- [ ] Implement `comm_read_byte()` +- [ ] Implement `comm_write_byte()` +- [ ] Add timeout configuration +- [ ] Add error recovery logic +- [ ] Implement thread-safe operations + +--- \ No newline at end of file diff --git a/main.c b/main.c index b047b6c..2451801 100644 --- a/main.c +++ b/main.c @@ -4,39 +4,32 @@ #include #include +#include "utils.h" #include "communication.h" extern struct sp_port *port; int main(int argc, char *argv[]) { comm_init_communication(); - - byte data = 205; - int size = 1; - printf("size: %d\n", size); - unsigned int timeout = 50 * size; //50 ms timeout per byte - - check(sp_nonblocking_write(port, &data, size)); - byte *buf = malloc(size + 1); - - int result = check(sp_blocking_read(port, buf, size, timeout)); - - if (result == size) { - printf("Received the same amount of bytes back \n"); + while (1) { + if (comm_await()) { + byte *buffer = malloc(sizeof(byte)); + if (sp_nonblocking_read(port, buffer, 1) == 1) { + byte *bits = malloc(sizeof(byte) * 8); + byte_to_bit_array(bits, *buffer); + printf("Data received: "); + for (int i = 7; i; i--) { + printf("%d", bits[i]); + } + printf("\n"); + free(buffer); + if (bits[7] == 1) { + free(bits); + break; + } + } + } } - buf[result] = '\0'; - printf("%s\n", buf); - - byte bits[8]; - uint8_to_bit_array(bits, buf); - - for (int i = 0; i < 8; i++) { - printf("%d ", bits[i]); - } - byte reconv_data = bit_array_to_uint8(bits); - printf("data: %d\n", reconv_data); - printf("\n"); - comm_end_communication(port); return 0; } diff --git a/utils.c b/utils.c new file mode 100644 index 0000000..1397a3e --- /dev/null +++ b/utils.c @@ -0,0 +1,23 @@ +// +// Created by nano on 4/26/25. +// + +#include "utils.h" +#include "communication.h" + +// Helper functions to convert from bits to bytes +void byte_to_bit_array(byte bit_array[], byte data) { + for (int i = 0; i < 8; i++) { + bit_array[i] = (data >> i) & 1; //shift through all bits and check if they're 1 + } +} + +void bit_array_to_byte(byte bit_array[], byte *data) { + *data=0; + u_int8_t currentpow=1; + + for (int i = 0; i < 8; i++) { + data+=bit_array[i]*currentpow; + currentpow*=2; + } //2's complement notation +} \ No newline at end of file diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..a557881 --- /dev/null +++ b/utils.h @@ -0,0 +1,13 @@ +// +// Created by nano on 4/26/25. +// +#include + +#ifndef UTILS_H +#define UTILS_H +typedef u_int8_t byte; + +void byte_to_bit_array(byte *bit_array, byte data); +void bit_array_to_byte(byte bit_array[], byte *data); + +#endif //UTILS_H