Skip to content

Instantly share code, notes, and snippets.

@superna9999
Created August 31, 2022 15:52
Show Gist options
  • Save superna9999/fa31b8b3b42f84c83560679a5f4c5593 to your computer and use it in GitHub Desktop.
Save superna9999/fa31b8b3b42f84c83560679a5f4c5593 to your computer and use it in GitHub Desktop.
no comments
#include <piccolo_config.h>
#include "termios.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "fcntl.h"
#include "unistd.h"
#include "sys/signal.h"
#include "sys/socket.h"
#include "sys/types.h"
#include "netinet/in.h"
#include "errno.h"
#include "PSTN.h"
#include <sys/select.h>
#include "time.h"
#include "stdbool.h"
#include "unistd.h"
#include "sys/ioctl.h"
#include <sys/select.h>
#include "uart.h"
struct termios ttyset;
static bool uarts_initialised = false;
static UART_t uarts[UART_NUMBERS];
static bool cb_in_progress;
static void UART1_transmitt(char *buffer_ptr, uint32_t size);
static void UART2_transmitt(char *buffer_ptr, uint32_t size);
static void UART3_transmitt(char *buffer_ptr, uint32_t size);
static void UART4_transmitt(char *buffer_ptr, uint32_t size);
static void UART5_transmitt(char *buffer_ptr, uint32_t size);
static void UARTUSB0_transmitt(char *buffer_ptr, uint32_t size);
static void UARTUSB1_transmitt(char *buffer_ptr, uint32_t size);
static void* UART1_worker(void *arg);
static void* UART2_worker(void *arg);
static void* UART3_worker(void *arg);
static void* UART4_worker(void *arg);
static void* UART5_worker(void *arg);
static void* UARTUSB0_worker(void *arg);
static void* UARTUSB1_worker(void *arg);
/* ttyO0 is reserved for the terminal */
#if(SDK_VERSION == 314)
const char* UART_tty_devices[] = { "/dev/ttyO1", "/dev/ttyO2", "/dev/ttyO3", "/dev/ttyO4", "/dev/ttyO5", "/dev/ttyUSB0", "/dev/ttyUSB1" };
#elif(SDK_VERSION == 404)
const char* UART_tty_devices[] = { "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyS4", "/dev/ttyS5", "/dev/ttyUSB0", "/dev/ttyUSB1" };
#else
#error "SDK_VERSION not supported. Supported versions are 314 and 414"
#endif
////"/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3", "/dev/ttyS4", "/dev/ttyS5"
//const char* UART_tty_devices[] = { "/dev/ttyO1", "/dev/ttyO2", "/dev/ttyO3", "/dev/ttyO4", "/dev/ttyO5", "/dev/ttyUSB0", "/dev/ttyUSB1" };
static uint32_t get_uart_bdr_mask(UART_baud_rate_t bdr)
{
switch (bdr) {
case UART_BAUD_2400:
return B2400;
case UART_BAUD_4800:
return B4800;
case UART_BAUD_9600:
return B9600;
case UART_BAUD_19200:
return B19200;
case UART_BAUD_38400:
return B38400;
case UART_BAUD_57600:
return B57600;
case UART_BAUD_115200:
return B115200;
default:
return B9600;
}
}
/**
* Initialise selected UART
* @param[in] modem_id modem
* @return char array with device name
*/
bool UART_open(UART_id_t id, UART_baud_rate_t bdr, UART_num_of_stop_bits_t stop_bits, UART_parity_t parity)
{
int err;
char* uart_dev = UART_get_device(id);
if (uart_dev != NULL) {
uarts[id].fd = open(uart_dev, O_RDWR | O_NOCTTY);
if (uarts[id].fd < 0) {
return false;
}
} else {
return false;
}
bzero(&ttyset, sizeof(ttyset));
err = cfsetispeed(&ttyset, get_uart_bdr_mask(bdr));
err += cfsetospeed(&ttyset, get_uart_bdr_mask(bdr));
ttyset.c_cflag = get_uart_bdr_mask(bdr) | /*CRTSCTS |*/CS8 | CLOCAL | CREAD;
if (stop_bits == UART_2STOP_BIT) {
ttyset.c_cflag |= CSTOPB;
}
if (parity == NO_PARITY) {
ttyset.c_cflag &= ~PARENB;
} else if (parity == EVEN_PARITY) {
ttyset.c_cflag |= PARENB;
ttyset.c_cflag &= ~PARODD;
} else if (parity == ODD_PARITY) {
ttyset.c_cflag |= (PARENB | PARODD);
}
ttyset.c_iflag = IGNPAR;
ttyset.c_oflag = 0;
/* set input mode (non-canonical, no echo,...) */
ttyset.c_lflag &= ~ICANON; /* Set non-canonical mode */
ttyset.c_cc[VTIME] = 100; /* Set timeout of 10.0 seconds */
ttyset.c_lflag = 0;
ttyset.c_cc[VTIME] = 0; /* inter-character timer unused */
ttyset.c_cc[VMIN] = 1; /* blocking read until 1 char received */
// fcntl(uarts[id].fd, F_SETFL, 0); // causes read to block until new characters are present /
//// fcntl(uarts[id].fd, F_SETFL, FNDELAY); // remove this call as it causes read to return immediately /
//
// fcntl(uarts[id].fd, F_SETOWN, getpid());
// fcntl(uarts[id].fd, F_SETFL, O_ASYNC);
err += tcflush(uarts[id].fd, TCIFLUSH);
err += tcsetattr(uarts[id].fd, TCSANOW, &ttyset);
if (err == 0) {
/* create thread for the UART */
switch (id) {
case UART_1:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UART1_worker, NULL);
break;
case UART_2:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UART2_worker, NULL);
break;
case UART_3:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UART3_worker, NULL);
break;
case UART_4:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UART4_worker, NULL);
break;
case UART_5:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UART5_worker, NULL);
break;
case UART_USB0:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UARTUSB0_worker, NULL);
break;
case UART_USB1:
pthread_create(&(uarts[id].uart_thread_id), NULL, &UARTUSB1_worker, NULL);
break;
default: {
return false;
}
}
return true;
} else {
return false;
}
}
/*
* Returns true if received message satisfies receiving criteria
*/
static bool UART_check_received(UART_id_t id, uint8_t received_byte)
{
UART_receiver_t *uart_receiver = &uarts[id].receiver;
char last_char = uart_receiver->last_char_received;
uart_receiver->last_char_received = received_byte;
if (uart_receiver->receive_mode == UART_RX_MODE_BINARY && uart_receiver->expected_bytes > 0) {
if ((uart_receiver->data_ptr) >= uart_receiver->expected_bytes) {
return true;
}
}
if (uart_receiver->receive_mode == UART_RX_MODE_STRING) {
switch (uart_receiver->receive_string_delimiter) {
case UART_STRING_DELIMITER_CRLF: {
if (last_char == '\r' && received_byte == '\n') {
return true;
}
break;
}
case UART_STRING_DELIMITER_LF: {
if (received_byte == '\n') {
return true;
}
break;
}
case UART_STRING_DELIMITER_CR: {
if (received_byte == '\r') {
return true;
}
break;
}
}
}
return false;
}
/**
* Reset receiving pointer to start receiving from beggining of internal buffer
* @param[in] id UART id
*/
void UART_reset_receiver(UART_id_t id)
{
uarts[id].receiver.data_ptr = 0;
uarts[id].receiver.received_size = 0;
}
/* moves all elements from desired position to the beggining of array */
static void move_buffer(uint8_t *buff, uint16_t size, uint16_t from)
{
int i;
for (i = 0; i < size; i++) {
buff[i] = buff[i + from];
}
}
/* general UART worker function */
static void* UART_worker(UART_id_t id, void *arg)
{
uint32_t bytes_avaiable;
uint16_t ptr;
uint16_t received_size;
UART_receiver_t *uart_receiver = &uarts[id].receiver;
bytes_avaiable = 0;
cb_in_progress = false;
while (1) {
ptr = uart_receiver->data_ptr;
bytes_avaiable = read(uarts[id].fd, &uart_receiver->data[uart_receiver->data_ptr], UART_RX_BUFFER_SIZE);
// printf("Bytes %d\n", bytes_avaiable);
if (ptr != uart_receiver->data_ptr) { /* pointer is changed during read blocking wait */
move_buffer((uint8_t *) uart_receiver->data, bytes_avaiable, ptr);
}
uart_receiver->data_ptr += bytes_avaiable;
uart_receiver->received_size = uart_receiver->data_ptr;
if (UART_check_received(id, uart_receiver->data[uart_receiver->data_ptr - 1])) {
received_size = uart_receiver->data_ptr;
UART_reset_receiver(id);
if (uart_receiver->receive_cb != NULL && uart_receiver->receiver_cb_enabled) {
cb_in_progress = true;
uart_receiver->receive_cb((char*) uart_receiver->data, received_size, (void*) id);
cb_in_progress = false;
}
}
}
return arg;
}
/**
* Read directly if there are any bytes available, otherwise return 0
* @param id
* @param buffer_ptr
* @return 0 if no bytes are available
*/
static uint16_t UART_read_direct(UART_id_t id, char *buffer_ptr)
{
int bytes_avail;
int tmp;
ioctl(uarts[id].fd, FIONREAD, &bytes_avail);
if (bytes_avail > 0) {
tmp = read(uarts[id].fd, buffer_ptr, UART_RX_BUFFER_SIZE);
return bytes_avail;
} else {
return 0;
}
}
uint16_t UART_get_received(UART_id_t id, char *buffer_ptr)
{
if (cb_in_progress) {
return UART_read_direct(id, buffer_ptr);
}
memcpy(buffer_ptr, uarts[id].receiver.data, uarts[id].receiver.received_size);
return uarts[id].receiver.received_size;
}
/**
* Check if UART is enabled/present in the system
* @param[in] id UART id
* @return true if UART is enabled
*/
bool UART_is_enabled(UART_id_t id)
{
if (id == UART_1 && UART1_ENABLED) {
return true;
}
if (id == UART_2 && UART2_ENABLED) {
return true;
}
if (id == UART_3 && UART3_ENABLED) {
return true;
}
if (id == UART_4 && UART4_ENABLED) {
return true;
}
if (id == UART_5 && UART5_ENABLED) {
return true;
}
if (id == UART_USB0 && UARTUSB_ENABLED) {
return true;
}
if (id == UART_USB1 && UARTUSB_ENABLED) {
return true;
}
return false;
}
/**
* Initialise selected UART variables and states and function pointers
* @param[in] id UART which is about to be initialized
* @return true if UART is present and properly initialised
*/
bool UART_init(UART_id_t id)
{
if (!UART_is_enabled(id)) {
return false;
}
uarts[id].fd = (int) NULL;
uarts[id].receiver.receive_cb = NULL;
uarts[id].id = id;
switch (id) {
case UART_1:
uarts[id].transmit_cb = UART1_transmitt;
break;
case UART_2:
uarts[id].transmit_cb = UART2_transmitt;
break;
case UART_3:
uarts[id].transmit_cb = UART3_transmitt;
break;
case UART_4:
uarts[id].transmit_cb = UART4_transmitt;
break;
case UART_5:
uarts[id].transmit_cb = UART5_transmitt;
break;
case UART_USB0:
uarts[id].transmit_cb = UARTUSB0_transmitt;
break;
case UART_USB1:
uarts[id].transmit_cb = UARTUSB1_transmitt;
break;
}
return true;
}
/**
* Initialise all UARTs in system to default values and states
*/
void UART_init_all()
{
int i;
if (!uarts_initialised) {
for (i = UART_1; i <= UART_USB1; i++) {
UART_init(i);
uarts_initialised = true;
}
}
}
/**
* Initialise selected UART
* @param[in] modem_id modem
* @return char array with device name
*/
char* UART_get_device(UART_id_t id)
{
if (id <= UART_USB1) {
return (char*) UART_tty_devices[id];
} else {
return NULL;
}
}
/**
* Wait for string to be received before invoking receiver callback
* @param[in] id UART id
* @param[in] lines number of text lines (terminated with delimiter)
* @param[in] delimiter defines how text lines delimitations shoud be handled
*/
void UART_receive_strings(UART_id_t id, uint8_t lines, UART_receive_string_delimiter_t delimiter)
{
uarts[id].receiver.expected_lines = lines;
uarts[id].receiver.receive_string_delimiter = delimiter;
uarts[id].receiver.receive_mode = UART_RX_MODE_STRING;
}
/**
* Wait for string to be received before invoking receiver callback
* @param[in] id UART id
* @param[in] expected_bytes bytes to receive before receiving callback invoking
*/
void UART_receive_data(UART_id_t id, uint16_t expected_bytes)
{
uarts[id].receiver.data_ptr = 0;
uarts[id].receiver.expected_bytes = expected_bytes;
uarts[id].receiver.receive_mode = UART_RX_MODE_BINARY;
}
/**
* Get UART receive mode
* @param[in] id UART id
* @return UART receive mode
*/
UART_receive_mode_t UART_get_receive_mode(UART_id_t id)
{
return uarts[id].receiver.receive_mode;
}
/*UNUSED*/
//static void set_termios_rec_bytes(UART_id_t id, uint16_t expected_bytes) {
//
// tcflush(uarts[id].fd, TCIOFLUSH);
// tcgetattr(uarts[id].fd, &ttyset);
// ttyset.c_cc[VMIN] = expected_bytes; /* blocking read until 1 char received */
// tcsetattr(uarts[id].fd, TCSANOW, &ttyset);
//}
/**
* Set callback function for receiver. Setting automatically enables callback if callback is not NULL
* @param[in] id UART id
* @param[in] receiver callback function
*/
void UART_set_receive_cb(UART_id_t id, stream_receiver_cb_t cb_funct)
{
uarts[id].receiver.receive_cb = cb_funct;
uarts[id].receiver.receiver_cb_enabled = cb_funct != NULL;
}
/**
* Set callback function for receiver.
* @param[in] id UART idasas
* @return pointer to receiver callback function
*/
stream_receiver_cb_t UART_get_receive_cb(UART_id_t id)
{
return uarts[id].receiver.receive_cb;
}
/**
* Enables/Disables UART receiver callback
* @param[in] id UART id
* @param[in] enable true to enable, false to disable
*/
void UART_enable_receive_cb(UART_id_t id, bool enable)
{
uarts[id].receiver.receiver_cb_enabled = enable;
}
/**
* Gets enabled state of selected UART receiver
* @param[in] id UART id
* @return true or false (enabled/disabled)
*/
bool UART_is_receive_cb_enabled(UART_id_t id)
{
return uarts[id].receiver.receiver_cb_enabled;
}
/**
* Transmits buffer on the UART
* @param[in] id UART id
* @param[in] buffer_ptr contains data to transmitt
* @param[in] size number of bytes for transmitting
*/
void UART_transmitt(UART_id_t id, char *buffer_ptr, uint32_t size)
{
FILE* f_ptr = (FILE*) uarts[id].fd;
if (f_ptr != NULL) {
write((int) f_ptr, buffer_ptr, size);
}
}
/* Transmitt wrappers */
static void UART1_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_1, buffer_ptr, size);
}
static void UART2_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_2, buffer_ptr, size);
}
static void UART3_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_3, buffer_ptr, size);
}
static void UART4_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_4, buffer_ptr, size);
}
static void UART5_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_5, buffer_ptr, size);
}
static void UARTUSB0_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_USB0, buffer_ptr, size);
}
static void UARTUSB1_transmitt(char *buffer_ptr, uint32_t size)
{
UART_transmitt(UART_USB1, buffer_ptr, size);
}
/**
* Gets transmitter funcition pointer for a UART
* @param[in] id UART id
* @return pointer to a transmitt function of an UART
*/
stream_transmitter_cb_t UART_get_transmitter(UART_id_t id)
{
return uarts[id].transmit_cb;
}
/* UART worker wrappers */
static void* UART1_worker(void *arg)
{
return UART_worker(UART_1, arg);
}
static void* UART2_worker(void *arg)
{
return UART_worker(UART_2, arg);
}
static void* UART3_worker(void *arg)
{
return UART_worker(UART_3, arg);
}
static void* UART4_worker(void *arg)
{
return UART_worker(UART_4, arg);
}
static void* UART5_worker(void *arg)
{
return UART_worker(UART_5, arg);
}
static void* UARTUSB0_worker(void *arg)
{
return UART_worker(UART_USB0, arg);
}
static void* UARTUSB1_worker(void *arg)
{
return UART_worker(UART_USB1, arg);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment