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
|
add_executable(serial
|
||||||
communication.c
|
communication.c
|
||||||
communication.h
|
communication.h
|
||||||
|
utils.c
|
||||||
|
utils.h
|
||||||
main.c)
|
main.c)
|
||||||
|
|
||||||
target_link_libraries(serial serialport)
|
target_link_libraries(serial serialport)
|
||||||
|
|||||||
@ -8,9 +8,10 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
struct sp_port ** port_list;
|
struct sp_port ** port_list;
|
||||||
struct sp_port * port;
|
struct sp_port * port;
|
||||||
|
struct sp_event_set *event_set;
|
||||||
|
|
||||||
void comm_init_communication() {
|
void comm_init_communication() {
|
||||||
/*
|
/*
|
||||||
@ -21,29 +22,39 @@ void comm_init_communication() {
|
|||||||
comm_list_serial_ports(port_list);
|
comm_list_serial_ports(port_list);
|
||||||
printf("Chose a port: ");
|
printf("Chose a port: ");
|
||||||
scanf("%d",&portnr);
|
scanf("%d",&portnr);
|
||||||
port=port_list[portnr];
|
sp_copy_port(port_list[portnr], &port);
|
||||||
|
sp_free_port_list(port_list);
|
||||||
comm_open_port(port);
|
comm_open_port(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void comm_end_communication(struct sp_port *port) {
|
void comm_end_communication(struct sp_port *port) {
|
||||||
/*
|
/*
|
||||||
* Ends the serial communication for the usb -> uart board
|
* Ends the serial communication for the usb -> uart board
|
||||||
*/
|
*/
|
||||||
check(sp_close(port));
|
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
|
// 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
|
//TODO: IMPLEMENT
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int comm_await() {
|
|
||||||
// Await data from the robot
|
|
||||||
//TODO: IMPLEMENT
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sp_port **comm_get_port_list() {
|
struct sp_port **comm_get_port_list() {
|
||||||
struct sp_port **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) {
|
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.
|
* 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_open(port,SP_MODE_READ_WRITE));
|
||||||
check(sp_set_baudrate(port,19200));
|
check(sp_set_baudrate(port,19200));
|
||||||
check(sp_set_bits(port,8));
|
check(sp_set_bits(port,8));
|
||||||
check(sp_set_parity(port,SP_PARITY_NONE));
|
check(sp_set_parity(port,SP_PARITY_NONE));
|
||||||
check(sp_set_stopbits(port,1));
|
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)
|
int check(enum sp_return result)
|
||||||
{
|
{
|
||||||
/* For this example we'll just exit on any error by calling abort(). */
|
/* 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;
|
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;
|
typedef u_int8_t byte;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the serial communication for the usb -> uart board
|
||||||
|
*/
|
||||||
void comm_init_communication();
|
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);
|
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);
|
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);
|
void comm_open_port(struct sp_port *port);
|
||||||
|
|
||||||
|
|
||||||
|
int comm_await();
|
||||||
|
|
||||||
|
|
||||||
int check(enum sp_return result);
|
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
|
#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
|
||||||
|
|
||||||
|
---
|
||||||
45
main.c
45
main.c
@ -4,39 +4,32 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
#include "communication.h"
|
#include "communication.h"
|
||||||
|
|
||||||
extern struct sp_port *port;
|
extern struct sp_port *port;
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
comm_init_communication();
|
comm_init_communication();
|
||||||
|
while (1) {
|
||||||
byte data = 205;
|
if (comm_await()) {
|
||||||
int size = 1;
|
byte *buffer = malloc(sizeof(byte));
|
||||||
printf("size: %d\n", size);
|
if (sp_nonblocking_read(port, buffer, 1) == 1) {
|
||||||
unsigned int timeout = 50 * size; //50 ms timeout per byte
|
byte *bits = malloc(sizeof(byte) * 8);
|
||||||
|
byte_to_bit_array(bits, *buffer);
|
||||||
check(sp_nonblocking_write(port, &data, size));
|
printf("Data received: ");
|
||||||
byte *buf = malloc(size + 1);
|
for (int i = 7; i; i--) {
|
||||||
|
printf("%d", bits[i]);
|
||||||
int result = check(sp_blocking_read(port, buf, size, timeout));
|
}
|
||||||
|
printf("\n");
|
||||||
if (result == size) {
|
free(buffer);
|
||||||
printf("Received the same amount of bytes back \n");
|
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);
|
comm_end_communication(port);
|
||||||
return 0;
|
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