211 lines
6.0 KiB
C
211 lines
6.0 KiB
C
//
|
|
// Created by nano on 4/26/25.
|
|
//
|
|
|
|
#include "communication.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
/**
|
|
* 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.
|
|
*/
|
|
void comm_open_port() {
|
|
|
|
check(sp_open(port, SP_MODE_READ_WRITE));
|
|
check(sp_set_baudrate(port, 9600));
|
|
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);
|
|
}
|
|
|
|
/**
|
|
* Wait till there is data available.
|
|
* @param timeout how much time in ms to wait for the data
|
|
* @returns SP_OK if data is ready.
|
|
* @returns SP_ERR_FAIL if data was not available before timeout ended.
|
|
*/
|
|
int comm_await_data_ready(int timeout) {
|
|
// Await data from the robot
|
|
return sp_wait(event_data_ready, timeout);
|
|
}
|
|
|
|
/**
|
|
* Wait till you can transmit again .
|
|
* @param timeout how much time in ms to wait for the data
|
|
* @returns SP_OK if data is ready.
|
|
* @returns SP_ERR_FAIL if uart module wasnt ready for transmit before timeout ended.
|
|
*/
|
|
int comm_await_ready_for_tx(int timeout) {
|
|
return sp_wait(event_ready_for_tx, timeout);
|
|
}
|
|
|
|
|
|
/**
|
|
* Read a number of bytes from the buffer, store them in data without blocking the process.
|
|
* @param data array where to store the data
|
|
* @param amount_of_bytes
|
|
* @return ALL_BYTES if the number of expected bytes was read
|
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
|
* @return ERROR if read fails
|
|
*/
|
|
comm_result comm_nonblocking_read(byte *data, int amount_of_bytes) {
|
|
//read available data
|
|
int recv_bytes = sp_nonblocking_read(port, data, amount_of_bytes);
|
|
if (recv_bytes == amount_of_bytes) {
|
|
return ALL_BYTES;
|
|
}
|
|
if (recv_bytes >= 0) {
|
|
return NOT_ENOUGH_BYTES;
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
/**
|
|
* Read a number of bytes from the buffer, store them in data, with a number of ms to wait in case that amount of data is not available..
|
|
* @param data array where to store the data
|
|
* @param amount_of_bytes
|
|
* @param timeout how much time in ms to wait for all data to be available.
|
|
* @return ALL_BYTES if the number of expected bytes was read
|
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
|
* @return ERROR if read fails
|
|
*/
|
|
comm_result comm_blocking_read(byte *data, int amount_of_bytes, int timeout) {
|
|
//read available data
|
|
int recv_bytes = sp_blocking_read(port, data, amount_of_bytes, timeout);
|
|
printf("RECV: %d\n",*data);
|
|
if (recv_bytes == amount_of_bytes) {
|
|
return ALL_BYTES;
|
|
}
|
|
if (recv_bytes >= 0) {
|
|
return NOT_ENOUGH_BYTES;
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
/**
|
|
* Write a number of bytes to the buffer, from data, with a number of ms to wait in case that amount of data is not available..
|
|
* @param data array where to store the data
|
|
* @param amount_of_bytes
|
|
* @param timeout how much time in ms to wait for all data to be available.
|
|
* @return ALL_BYTES if the number of expected bytes was read
|
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
|
* @return ERROR if read fails
|
|
*/
|
|
comm_result 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
|
|
int sent_bytes = sp_blocking_write(port, data, amount_of_bytes, timeout);
|
|
printf("SEND: %d \n",*data);
|
|
|
|
if (sent_bytes == amount_of_bytes) {
|
|
return ALL_BYTES;
|
|
}
|
|
if (sent_bytes >= 0) {
|
|
return NOT_ENOUGH_BYTES;
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
/**
|
|
* Write a number of bytes to the buffer, from data.
|
|
* @param data array where to store the data
|
|
* @param amount_of_bytes
|
|
* @return ALL_BYTES if the number of expected bytes was read
|
|
* @return NOT_ENOUGH_BYTES if read less than expected
|
|
* @return ERROR if read fails
|
|
*/
|
|
comm_result 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
|
|
int sent_bytes = sp_nonblocking_write(port, data, amount_of_bytes);
|
|
if (sent_bytes == amount_of_bytes) {
|
|
return ALL_BYTES;
|
|
}
|
|
if (sent_bytes >= 0) {
|
|
return NOT_ENOUGH_BYTES;
|
|
}
|
|
return ERROR;
|
|
}
|
|
|
|
//Check if bytes are left to be sent
|
|
int comm_output_waiting() {
|
|
return sp_output_waiting(port);
|
|
}
|
|
|
|
/** 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;
|
|
}
|
|
}
|