Commit 00978df2 authored by ryukoposting's avatar ryukoposting

add PC-side state machine

parent c48c1d43
......@@ -44,7 +44,7 @@ used with PC-GPIO with just a few dozen lines of code. However, implementations
exist for the microcontrollers listed below:
- Arduino
- DUE: fully supported. Supported natively in the Arduino IDE. Will also be supported
- DUE: in progress. Supported natively in the Arduino IDE. Will also be supported
without Arduino library dependencies via direct support for the SAM3X8E.
- UNO: planned.
- Atmel
......@@ -55,6 +55,33 @@ exist for the microcontrollers listed below:
- Infineon
- XMC1404: planned.
### Using the Library
Adding PC-GPIO to a CMake project:
1. Assuming the library is in a subdirectory of your project named 'PC-GPIO':
```
cmake_minimum_required(VERSION 3.5)
project(your_project_name LANGUAGES C)
set(CMAKE_C_STANDARD 11)
add_subdirectory(PC-GPIO)
set(CMAKE_EXE_LINKER_FLAGS "-pthread")
add_executable(your_project_name your_project_main.c)
target_link_libraries(your_project_name LINK_PUBLIC pcgpio)
```
Adding PC-GPIO to an Arduino project:
1. Download the complete PC-GPIO source.
2. Open your Arduino project folder (the one that includes the .ino file).
3. In this directory, extract the PC-GPIO source into a folder called "PC-GPIO"
So there will be 2 things in the project folder, the .ino file and a folder
called PC-GPIO.
4. Import PC-GPIO into your arduino project by adding `#include "PC-GPIO/pcgpio_global.h"
To the top of your arduino code.
### License
Copyright (C) 2018 ryukoposting
......
......@@ -31,7 +31,7 @@
char status_string[48];
static int PCGPIO_BufferPut___(struct PCGPIO_Properties* s, char c) {
static int PCGPIO_BufferPut___(struct PCGPIO_Properties *s, char c) {
//if there is space in the buffer
if ( s->end != ((s->start + 1023) % 1024)) {
s->rxbuffer[s->end] = c;
......@@ -42,11 +42,17 @@ static int PCGPIO_BufferPut___(struct PCGPIO_Properties* s, char c) {
return -1;
}
static void PCGPIO_BufferClear___(struct PCGPIO_Properties* s) {
static void PCGPIO_BufferClear___(struct PCGPIO_Properties *s) {
s->start = 0;
s->end = 0;
}
static unsigned char PCGPIO_GetNextChar___(struct PCGPIO_Properties *s) {
unsigned char out = s->rxbuffer[s->start];
if(++(s->start) >= 1024) s->start = 0;
return out;
}
void *PCGPIO_ThreadHandler___(void* properties) {
struct pollfd ufds;
unsigned char buff[1024];
......@@ -62,48 +68,148 @@ void *PCGPIO_ThreadHandler___(void* properties) {
while(p->running != 0) {
poll_result = poll(&ufds, 1, 2000);
//
if(poll_result > 0) {
int cnt = read(p->fd, buff, 1023);
if(cnt > 0) {
buff[cnt] = '\0';
// make serial callback (not pcgpio callback)
for(int i = 0; i < cnt; i++) {
PCGPIO_BufferPut___(p, buff[i]);
}
int complete_message_received = 0;
if(p->rxbuffer[p->start] != 0xA5) {
p->error_handler(p, PCGPIO_STATUS_INVALID_CALLBACK);
} else if(cnt < 0) {
// printf("serial port disconnected!\n");
error_found = PCGPIO_STATUS_PORT_ERROR;
p->error_handler(p, PCGPIO_STATUS_PORT_ERROR);
} else {
// no new serial data on this cycle, work on whatever
// is available in rxbuffer
unsigned char in = PCGPIO_GetNextChar___(p);
unsigned int next_state = 0x7FFF; // 0x7FFF = error recovery
switch(p->state) {
case 0: // no message currently in transmission
if(in == 0xA5) {
p->checksum = 0;
next_state = 1;
} else {
next_state = 0;
}
break;
case 1: // got a start byte
p->receiver_callback.callback_type = (enum PCGPIO_CallbackType)in;
next_state = 0x100 + in;
p->checksum += in;
break;
case 0x100: // first data byte of device identifier
p->receiver_callback.callback.mcu_identity.mcu_identifier = (in << 8);
next_state = 0x200;
p->checksum += in;
break;
case 0x200: // second data byte of device identifier
p->receiver_callback.callback.mcu_identity.mcu_identifier |= in;
next_state = 0xAAA;
p->checksum += in;
break;
case 0x103: // first data byte of digital read
p->receiver_callback.callback.read_digital.pin = in;
next_state = 0x203;
p->checksum += in;
break;
case 0x203: // second data byte of digital read
p->receiver_callback.callback.read_digital.value = in;
next_state = 0xAAA;
p->checksum += in;
break;
case 0x104: // first data byte of analog read
p->receiver_callback.callback.read_analog.pin = in;
next_state = 0x204;
p->checksum += in;
break;
case 0x204: // second data byte of analog read
p->receiver_callback.callback.read_analog.value = ((in & 0xFF) << 24);
next_state = 0x304;
p->checksum += in;
break;
case 0x304: // third data byte of analog read
p->receiver_callback.callback.read_analog.value |= ((in & 0xFF) << 16);
next_state = 0x404;
p->checksum += in;
break;
case 0x404: // fourth data byte of analog read
p->receiver_callback.callback.read_analog.value |= ((in & 0xFF) << 8);
next_state = 0x504;
p->checksum += in;
break;
case 0x504: // fifth data byte of analog read
p->receiver_callback.callback.read_analog.value |= (in & 0xFF);
next_state = 0xAAA;
p->checksum += in;
break;
for(int i = p->start; i < ((p->end > p->start) ? (p->end) : 1024); i++) {
case 0x111: // first data byte of pinconf
p->receiver_callback.callback.get_pin_config.pin = in;
next_state = 0x211;
p->checksum += in;
break;
case 0x211: // first data byte of pinconf
p->receiver_callback.callback.get_pin_config.conf = in;
next_state = 0xAAA;
p->checksum += in;
break;
case 0xAAA: // checksum byte
if((p->checksum) == (in & 0xFF)) {
next_state = 0xFFFF;
} else {
next_state = 0x7FFF;
p->error_handler(p, PCGPIO_STATUS_INCORRECT_CHECKSUM);
}
if((p->start) > (p->end)) {
for(int i = 0; i < p->end; i++) {
break;
case 0x7FFF: // error recovery state
if(in == 0x0A) {
next_state = 0;
} else if(in == 0xA5) {
next_state = 1;
}
break;
case 0xFFFF: // stop byte state
if(in == 0x0A) {
next_state = 0;
p->callback_handler(p, p->receiver_callback);
} else {
next_state = 0x7FFF;
p->error_handler(p, PCGPIO_STATUS_INCORRECT_STOPBYTE);
}
break;
} else if(cnt < 0) {
// printf("serial port disconnected!\n");
error_found = PCGPIO_STATUS_PORT_ERROR;
p->error_handler(p, PCGPIO_STATUS_PORT_ERROR);
} //else <- cnt == 0, nothing in buffer
default:
next_state = 0x7FFF;
p->error_handler(p, PCGPIO_STATUS_INVALID_CALLBACK);
}
p->state = next_state;
}
} else if(poll_result < 0) {
printf("polling error!\n");
error_found = PCGPIO_STATUS_POLLING_ERROR;
p->error_handler(p, PCGPIO_STATUS_POLLING_ERROR);
break; // this kills the thread?
}
}
if(error_found) {
p->running = 0;
}
}
poll_result = close(p->fd);
printf("serial port closing\n");
......@@ -120,7 +226,7 @@ unsigned char PCGPIO_MakeMethodChecksum(unsigned char* bytes, int length) {
}
enum PCGPIO_Status PCGPIO_Init(struct PCGPIO_Properties *const properties, char *port_name,
void(*callback_handler)(struct PCGPIO_Callback *callback),
void(*callback_handler)(struct PCGPIO_Properties *properties, struct PCGPIO_Callback callback),
void(*error_handler)(struct PCGPIO_Properties *properties, enum PCGPIO_Status status)) {
if(properties == NULL) return PCGPIO_STATUS_NULL_PTR;
if(strlen(port_name) > 32) return PCGPIO_STATUS_INVALID_PARAMETER;
......@@ -128,6 +234,7 @@ enum PCGPIO_Status PCGPIO_Init(struct PCGPIO_Properties *const properties, char
properties->pthread_function = &PCGPIO_ThreadHandler___;
properties->callback_handler = callback_handler;
properties->error_handler = error_handler;
properties->state = 0;
strncpy(properties->port_name, port_name, 32);
// open port
......@@ -256,6 +363,18 @@ char const *const PCGPIO_StatusAsString(enum PCGPIO_Status status) {
case PCGPIO_STATUS_POLLING_ERROR:
strcpy(status_string, "PCGPIO_STATUS_POLLING_ERROR");
break;
case PCGPIO_STATUS_INCORRECT_CHECKSUM:
strcpy(status_string, "PCGPIO_STATUS_INCORRECT_CHECKSUM");
break;
case PCGPIO_STATUS_INCORRECT_STOPBYTE:
strcpy(status_string, "PCGPIO_STATUS_INCORRECT_STOPBYTE");
break;
case PCGPIO_STATUS_IN_RECOVERY_STATE:
strcpy(status_string, "PCGPIO_STATUS_IN_RECOVERY_STATE");
break;
case PCGPIO_STATUS_INTERNAL_FAILURE:
strcpy(status_string, "PCGPIO_STATUS_INTERNAL_FAILURE");
break;
default:
strcpy(status_string, "UNDEFINED");
}
......
......@@ -36,21 +36,23 @@ extern "C" {
struct PCGPIO_Properties {
#if defined(__unix__)
int fd;
int state;
unsigned int state;
struct PCGPIO_Callback receiver_callback;
unsigned char checksum;
int running;
unsigned char rxbuffer[1024];
int start, end;
pthread_t rx_thread;
void*(*pthread_function)(void*);
#endif
void(*callback_handler)(struct PCGPIO_Callback *);
void(*callback_handler)(struct PCGPIO_Properties *, struct PCGPIO_Callback);
void(*error_handler)(struct PCGPIO_Properties *, enum PCGPIO_Status);
unsigned int mcu_identity;
char port_name[32];
};
enum PCGPIO_Status PCGPIO_Init(struct PCGPIO_Properties *const properties, char *port_name,
void(*callback_handler)(struct PCGPIO_Callback *callback),
void(*callback_handler)(struct PCGPIO_Properties *properties, struct PCGPIO_Callback callback),
void(*error_handler)(struct PCGPIO_Properties *properties, enum PCGPIO_Status status));
enum PCGPIO_Status PCGPIO_TransmitMethod(struct PCGPIO_Properties *const properties, struct PCGPIO_Method *const method);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment