some refactoring, a little more code and a bit of documentation
This commit is contained in:
parent
d2c73c9fb1
commit
dbca9b0d10
@ -6,6 +6,8 @@ include_directories(.)
|
||||
add_executable(serial
|
||||
communication.c
|
||||
communication.h
|
||||
utils.c
|
||||
utils.h
|
||||
main.c)
|
||||
|
||||
target_link_libraries(serial serialport)
|
||||
|
||||
@ -8,9 +8,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
199
docs/readme.md
Normal file
199
docs/readme.md
Normal file
@ -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
|
||||
|
||||
---
|
||||
41
main.c
41
main.c
@ -4,39 +4,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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");
|
||||
}
|
||||
buf[result] = '\0';
|
||||
printf("%s\n", buf);
|
||||
|
||||
byte bits[8];
|
||||
uint8_to_bit_array(bits, buf);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
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]);
|
||||
}
|
||||
byte reconv_data = bit_array_to_uint8(bits);
|
||||
printf("data: %d\n", reconv_data);
|
||||
printf("\n");
|
||||
|
||||
free(buffer);
|
||||
if (bits[7] == 1) {
|
||||
free(bits);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
comm_end_communication(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
23
utils.c
Normal file
23
utils.c
Normal file
@ -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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user