Skip to content

Instantly share code, notes, and snippets.

Created May 12, 2015 22:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/981a9b19a51993900ceb to your computer and use it in GitHub Desktop.
Save anonymous/981a9b19a51993900ceb to your computer and use it in GitHub Desktop.
serial.c
// serial.c
// -----------------------------------------------------------------------
#include <fcntl.h>
#include <termios.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
#include <errno.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/signal.h>
#include "h/xb_log.h"
#include "h/debug.h"
#include "h/circular.h"
// -----------------------------------------------------------------------
#define BAUDRATE B9600
#define DEVICE "/dev/ttyAMA0"
// -----------------------------------------------------------------------
static int read_fd;
static int write_fd;
static struct termios tty;
static pthread_t rx_thread;
// -----------------------------------------------------------------------
// return true if there is any serial data available for reading
bool serial_available(void)
{
int c = circular_count();
return(0 != c);
}
// -----------------------------------------------------------------------
uint8_t serial_read(void)
{
uint8_t c;
while(!serial_available())
;
c = circular_get();
return c;
}
// -----------------------------------------------------------------------
int serial_write(uint8_t *p, uint8_t n)
{
int z;
for(;;)
{
z = write(write_fd, p, n);
if(!(z < 0))
{
break;
}
usleep(50);
}
return z;
}
// -----------------------------------------------------------------------
int serial_writec(uint8_t c)
{
int cc;
for(;;)
{
cc = serial_write(&c, 1);
if(!(cc < 0))
{
break;
}
usleep(50);
}
return cc;
}
// -----------------------------------------------------------------------
// copy data into circular buffer after a read
static void copy_data(uint8_t *p, uint8_t n)
{
int i;
for(i = 0; i < n; i++)
{
circular_put(p[i]);
}
}
// -----------------------------------------------------------------------
void *rx_handler(void *p)
{
int res;
uint8_t tmp[256];
for(;;)
{
for(;;)
{
res = read(read_fd, &tmp[0], 255);
if(0 != res)
{
break;
}
usleep(100);
}
if(res == -1)
{
xb_log("serial", "Read Error %d", errno);
usleep(100);
continue;
}
else if(0 == res)
{
xb_log("serial", "Read returned with zero bytes wtf");
}
tmp[res] = 0;
printf("%s\n", tmp);
#ifdef DEBUG
xb_log("serial", "rx = %s", tmp);
#endif
copy_data(&tmp[0], res);
}
return NULL;
}
// -----------------------------------------------------------------------
#define C_CFLAG (CS8 | CLOCAL | CREAD)
#define C_LFLAG (ECHO | ISIG | ECHOE | ICANON)
void tty_init(int fd)
{
tcgetattr(fd, &tty);
cfsetispeed(&tty, BAUDRATE);
cfsetospeed(&tty, BAUDRATE);
tty.c_cflag &= ~(PARENB | CSIZE | CRTSCTS);
tty.c_cflag |= C_CFLAG;
tty.c_iflag &= ~(IXOFF | IXANY | IXON);
tty.c_iflag |= (IGNPAR | ICRNL | ONLCR);
tty.c_oflag = 0;
tty.c_lflag &= ~C_LFLAG;
tty.c_cc[VMIN] = 1;
tty.c_cc[VTIME] = 5;
tcsetattr(fd, TCSANOW, &tty);
usleep(100);
}
// -----------------------------------------------------------------------
// initialize serial comms to xbee module
void init_serial(void)
{
read_fd = open(DEVICE, O_RDONLY | O_NOCTTY);
if(read_fd < 0)
{
xb_log("serial", "Failed To Open Serial Port for Read");
exit(-1);
}
write_fd = open(DEVICE, O_WRONLY | O_NOCTTY);
if(write_fd < 0)
{
xb_log("serial", "Failed To Open Serial Port for Write");
exit(-1);
}
tcflush(read_fd, TCIFLUSH);
tcflush(write_fd, TCOFLUSH);
tty_init(read_fd); // this configures the port, not the fd
if(0 != pthread_create(&rx_thread, NULL, &rx_handler, NULL))
{
xb_log("serial", "Failed to create RX Thread");
exit(-1);
}
}
// =======================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment