Commit 34df477f authored by ryukoposting's avatar ryukoposting

cross-platform MCU state machines

parent 5631122a
......@@ -18,28 +18,190 @@
// email: epg@tfwno.gf
#if defined(PCGPIO_TARGET_ARCHITECTURE_ARDUINO_DUE)
#pragma message("found implementation for DUE")
#include "../pcgpio_mcu.h"
// due pin numbers: all digital pins same as what's printed on the board
// analog pins: 54 + n, so A0 is 54, A1 is 55, etc.
// DAC0 = 66
// DAC1 = 67
// SDA1 = 68
// SCL1 = 69
// CANRX = 70
// CANTX = 71
void TC7_Handler() {
TC_GetStatus(TC2, 1); // clears the interrupt
// digital IO
for(int i = 0; i < 54; i++) {
uint8_t setting = pin_modes[i] & 0xF0;
switch(setting) {
case 0:
if((pin_modes[i] & 0x0C) == 0x0C) { // both edge capture
uint8_t read = digitalRead(i);
if(read != pin_last_scan[i]) {
PCGPIO_SendDigitalInputRead(i, read);
}
pin_last_scan[i] = read;
} else if(pin_modes[i] & 0x04) { // rising edge capture
uint8_t read = digitalRead(i);
if(read > pin_last_scan[i]) {
PCGPIO_SendDigitalInputRead(i, read);
}
pin_last_scan[i] = read;
} else if(pin_modes[i] & 0x08) { // falling edge capture
uint8_t read = digitalRead(i);
if(read < pin_last_scan[i]) {
PCGPIO_SendDigitalInputRead(i, read);
}
pin_last_scan[i] = read;
}
break;
// nothing else currently needed for this,
// more stuff may be here at some point in the future
}
}
}
enum PCGPIO_Status PCGPIO_Start() {
analogWriteResolution(16);
Serial.begin(115200);
state = 0;
receiver_method = {};
}
enum PCGPIO_Status PCGPIO_TransmitCallback(struct PCGPIO_Callback *callback) {
}
pmc_set_writeprotect(false);
pmc_enable_periph_clk(ID_TC7);
/* we want wavesel 01 with RC */
TC_Configure(/* clock */TC2,/* channel */1, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK4);
TC_SetRC(TC2, 1, 656); // 656.25 = 1ms
TC_Start(TC2, 1);
enum PCGPIO_Status PCGPIO_SendDigitalInputRead(uint8_t pin) {
TC2->TC_CHANNEL[1].TC_IER=TC_IER_CPCS;
TC2->TC_CHANNEL[1].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(TC7_IRQn);
for(int i = 0; i < 62; i++) {
// special case state used for debugging erroneous captures
pin_last_scan[i] = 0xF0;
}
return PCGPIO_STATUS_OK;
}
enum PCGPIO_Status PCGPIO_SendAnalogInputRead(uint8_t pin) {
enum PCGPIO_Status PCGPIO_TransmitCallback(struct PCGPIO_Callback *callback) {
uint8_t buffer[16] = {0xA5, callback->callback_type, };
int length = 0;
switch(callback->callback_type) {
case PCGPIO_CALLBACKTYPE_MCUIDENTITY:
length = 6;
buffer[2] = (((callback->callback.mcu_identity.mcu_identifier) >> 8) & 0xFF);
buffer[3] = ((callback->callback.mcu_identity.mcu_identifier) & 0xFF);
buffer[4] = ((callback->callback_type + buffer[2] + buffer[3]) & 0xFF);
buffer[5] = 0x0A;
break;
case PCGPIO_CALLBACKTYPE_READDIGITAL:
length = 6;
buffer[2] = callback->callback.read_digital.pin;
buffer[3] = callback->callback.read_digital.value;
buffer[4] = ((callback->callback_type + buffer[2] + buffer[3]) & 0xFF);
buffer[5] = 0x0A;
break;
case PCGPIO_CALLBACKTYPE_READANALOG:
length = 9;
//TODO: logic for resolution bitshifts should go here
buffer[2] = callback->callback.read_analog.pin;
buffer[3] = ((callback->callback.read_analog.value >> 24) & 0xFF);
buffer[4] = ((callback->callback.read_analog.value >> 16) & 0xFF);
buffer[5] = ((callback->callback.read_analog.value >> 8) & 0xFF);
buffer[6] = callback->callback.read_analog.value & 0xFF;
buffer[7] = ((buffer[1] + buffer[2] + buffer[3] + buffer[4] + buffer[5] + buffer[6]) & 0xFF);
buffer[8] = 0x0A;
break;
case PCGPIO_CALLBACKTYPE_GETPINCONFIG:
length = 6;
buffer[2] = callback->callback.get_pin_config.pin;
buffer[3] = callback->callback.get_pin_config.conf;
buffer[4] = ((callback->callback_type + buffer[2] + buffer[3]) & 0xFF);
buffer[5] = 0x0A;
break;
default:
return PCGPIO_STATUS_INVALID_CALLBACK;
}
Serial.write(buffer, length);
return PCGPIO_STATUS_OK;
}
enum PCGPIO_Status PCGPIO_SendPinConfig(uint8_t pin) {
enum PCGPIO_Status PCGPIO_ProcessMethod(struct PCGPIO_Method *method) {
struct PCGPIO_Callback callback;
switch(method->method_type) {
case PCGPIO_METHODTYPE_MCUIDENTITY: {
callback.callback_type = PCGPIO_CALLBACKTYPE_MCUIDENTITY;
struct PCGPIO_CALLBACK_MCUIdentity mcu_identity = {
.mcu_identifier = PCGPIO_GLOBAL_MCU_ID
};
callback.callback.mcu_identity = mcu_identity;
PCGPIO_TransmitCallback(&callback);
}
break;
case PCGPIO_METHODTYPE_IOCONFIG:
if((method->method.io_pin_config.pin) < 54) {
if((method->method.io_pin_config.conf & 0xF0) == 0) { // is an input
// pullup/pulldown configuration
switch((method->method.io_pin_config.conf) & 0x03) {
case 0: // no pullups or pulldowns
pinMode(method->method.io_pin_config.pin, INPUT);
pin_modes[method->method.io_pin_config.pin] = method->method.io_pin_config.conf;
break;
case 1: // pulldown
/* not available on DUE */
break;
case 2: // pullup
pinMode(method->method.io_pin_config.pin, INPUT_PULLUP);
pin_modes[method->method.io_pin_config.pin] = method->method.io_pin_config.conf;
break;
}
// input capture on DUE is handled in interrupt
if((method->method.io_pin_config.conf) & 0x0C) {
pin_last_scan[method->method.io_pin_config.pin] = digitalRead(method->method.io_pin_config.pin);
}
} else if((method->method.io_pin_config.conf & 0xF0) == 0x10) { // is an output
if((method->method.io_pin_config.conf == 0x17) || (method->method.io_pin_config.conf == 0x10)) {
// DUE doesn't implement open drain outputs, and PWM config is
// the same as normal outputs
pinMode(method->method.io_pin_config.pin, OUTPUT);
pin_modes[method->method.io_pin_config.pin] = method->method.io_pin_config.conf;
}
}
} else {
}
break;
case PCGPIO_METHODTYPE_WRITEDIGITAL:
if(method->method.write_digital.pin < 54) {
if(pin_modes[(method->method.write_digital.pin)] == 0x17) {
// is a PWM pin
analogWrite(method->method.write_digital.pin, method->method.write_digital.value);
} else {
digitalWrite(method->method.write_digital.pin, method->method.write_digital.value);
}
}
break;
case PCGPIO_METHODTYPE_READDIGITAL:
break;
case PCGPIO_METHODTYPE_READANALOG:
break;
case PCGPIO_METHODTYPE_GETPINCONFIG:
break;
default:
return PCGPIO_STATUS_INVALID_METHOD;
}
return PCGPIO_STATUS_OK;
}
#endif
......@@ -24,24 +24,8 @@ enum PCGPIO_Status PCGPIO_Start() {
}
enum PCGPIO_Status PCGPIO_ProcessNextByte() {
}
enum PCGPIO_Status PCGPIO_TransmitCallback(struct PCGPIO_Callback *callback) {
}
enum PCGPIO_Status PCGPIO_SendDigitalInputRead(uint8_t pin) {
}
enum PCGPIO_Status PCGPIO_SendAnalogInputRead(uint8_t pin) {
}
enum PCGPIO_Status PCGPIO_SendPinConfig(uint8_t pin) {
}
#endif
......@@ -16,73 +16,82 @@ enum PCGPIO_Status PCGPIO_SendMCUID() {
}
enum PCGPIO_Status PCGPIO_ProcessNextByte(uint8_t in) {
switch(state) {
case 0: // no message currently in transmission
if(in == 0xA5) {
checksum = 0;
next_state = 1;
} else {
next_state = 0x7FFF;
return PCGPIO_STATUS_POLLING_ERROR;
next_state = 0;
}
break;
case 1: // got a start byte. figure out what method it is
receiver_method.method_type = (enum PCGPIO_MethodType)in;
next_state = 0x100 + in;
checksum += (in & 0xFF);
checksum += in;
break;
case 0x100: // checksum byte
if(checksum == in) {
if(checksum == (in & 0xFF)) {
next_state = 0xFFFF;
} else {
next_state = 0x7FFF;
state = 0x7FFF;
return PCGPIO_STATUS_INCORRECT_CHECKSUM;
}
break;
case 0x101: // first data byte of IOPinConfig method
receiver_method.method.io_pin_config.pin = in;
checksum += in;
next_state = 0x201;
break;
case 0x201: // second data byte of IOPinConfig method
receiver_method.method.io_pin_config.conf = in;
checksum += in;
next_state = 0x100;
break;
case 0x102: // first data byte of WriteDigital method
receiver_method.method.write_digital.pin = in;
checksum += in;
next_state = 0x202;
break;
case 0x202: // second data byte of WriteDigital method
receiver_method.method.write_digital.value = (in << 8);
checksum += in;
next_state = 0x302;
break;
case 0x301: // third data byte of WriteDigital method
receiver_method.method.write_digital.value |= (in & 0x00FF);
checksum += in;
next_state = 0x100;
break;
case 0x103: // first data byte of ReadDigital method
receiver_method.method.read_digital.pin = in;
checksum += in;
next_state = 0x100;
break;
case 0x104: // first data byte of ReadAnalog method
receiver_method.method.read_analog.pin = in;
checksum += in;
next_state = 0x100;
break;
case 0x111: // first data byte of GetPinConfig method
receiver_method.method.read_analog.pin = in;
checksum += in;
next_state = 0x100;
break;
case 0x7FFF: // error recovery state
if(in == 0x0A) {
next_state = 0;
} else if(in == 0xA5) {
next_state = 1;
} else {
return PCGPIO_STATUS_IN_RECOVERY_STATE;
}
break;
......@@ -90,17 +99,55 @@ enum PCGPIO_Status PCGPIO_ProcessNextByte(uint8_t in) {
case 0xFFFF: // should get stop byte
if(in == 0x0A) {
// we have gotten a complete, properly formatted method!
next_state = 0;
state = 0;
return PCGPIO_ProcessMethod(&receiver_method);
} else {
next_state = 0x7FFF;
state = 0x7FFF;
return PCGPIO_STATUS_INCORRECT_STOPBYTE;
}
break;
default:
next_state = 0x7FFF;
state = 0x7FFF;
}
state = next_state;
return PCGPIO_STATUS_OK;
}
enum PCGPIO_Status PCGPIO_SendDigitalInputRead(uint8_t pin, uint8_t value) {
struct PCGPIO_Callback callback = {
.callback_type = PCGPIO_CALLBACKTYPE_READDIGITAL
};
struct PCGPIO_CALLBACK_ReadDigital read_digital = {
.pin = pin,
.value = value
};
callback.callback.read_digital = read_digital;
return PCGPIO_TransmitCallback(&callback);
}
enum PCGPIO_Status PCGPIO_SendAnalogInputRead(uint8_t pin, uint32_t value) {
struct PCGPIO_Callback callback = {
.callback_type = PCGPIO_CALLBACKTYPE_READANALOG
};
struct PCGPIO_CALLBACK_ReadAnalog read_analog = {
.pin = pin,
.value = value
};
callback.callback.read_analog = read_analog;
return PCGPIO_TransmitCallback(&callback);
}
enum PCGPIO_Status PCGPIO_SendPinConfig(uint8_t pin, uint8_t conf) {
struct PCGPIO_Callback callback = {
.callback_type = PCGPIO_CALLBACKTYPE_GETPINCONFIG
};
struct PCGPIO_CALLBACK_GetPinConfig get_pin_config = {
.pin = pin,
.conf = conf
};
callback.callback.get_pin_config = get_pin_config;
return PCGPIO_TransmitCallback(&callback);
}
......@@ -25,6 +25,9 @@
#ifdef __cplusplus
extern "C" {
#endif
uint8_t pin_modes[PCGPIO_PIN_COUNT] = {};
uint8_t pin_last_scan[PCGPIO_PIN_COUNT] = {};
struct PCGPIO_Method receiver_method;
......@@ -38,16 +41,20 @@ enum PCGPIO_Status PCGPIO_ProcessMethod(struct PCGPIO_Method *method);
enum PCGPIO_Status PCGPIO_SendMCUID();
enum PCGPIO_Status PCGPIO_SendDigitalInputRead(uint8_t pin);
enum PCGPIO_Status PCGPIO_SendDigitalInputRead(uint8_t pin, uint8_t value);
enum PCGPIO_Status PCGPIO_SendAnalogInputRead(uint8_t pin);
enum PCGPIO_Status PCGPIO_SendPinConfig(uint8_t pin);
enum PCGPIO_Status PCGPIO_SendAnalogInputRead(uint8_t pin, uint32_t value);
enum PCGPIO_Status PCGPIO_SendPinConfig(uint8_t pin, uint8_t conf);
#ifdef __cplusplus
}
#endif
#ifdef PCGPIO_TARGET_ARCHITECTURE_ARDUINO_DUE
#include "pcgpio_mcu-common.c"
#include "arduino/pcgpio_mcu-due.c"
#endif
#endif // PCGPIO_MCU_H_
......@@ -19,6 +19,17 @@
#include "pcgpio_host.h"
enum PCGPIO_Status PCGPIO_RequestMCUID(struct PCGPIO_Properties *const properties) {
struct PCGPIO_METHOD_MCUIdentity mcu_identity = {
};
struct PCGPIO_Method method = {
.method_type = PCGPIO_METHODTYPE_MCUIDENTITY
};
method.method.mcu_identity = mcu_identity;
return PCGPIO_TransmitMethod(properties, &method);
}
enum PCGPIO_Status PCGPIO_IOConfig(struct PCGPIO_Properties *const properties, uint8_t pin, enum PCGPIO_PinConfig config) {
struct PCGPIO_METHOD_IOPinConfig io_pin_config = {
.pin = pin,
......
......@@ -27,6 +27,7 @@
#if defined(__PIC24FJ16GA002__) || defined(__PIC24FJ32GA002__) || defined(__PIC24FJ48GA002__) || defined(__PIC24FJ64GA002__)
#define PCGPIO_TARGET_ARCHITECTURE_PIC24
#define PCGPIO_GLOBAL_MCU_ID 0x0100
#define PCGPIO_PIN_COUNT 17
#include "mcu/pcgpio_mcu.h"
#ifdef PCGPIO_SHOW_COMPILER_MESSAGES
......@@ -37,6 +38,7 @@
#elif defined(__PIC24FJ16GA004__) || defined(__PIC24FJ32GA004__) || defined(__PIC24FJ48GA004__) || defined(__PIC24FJ64GA004__)
#define PCGPIO_TARGET_ARCHITECTURE_PIC24
#define PCGPIO_GLOBAL_MCU_ID 0x0101
#define PCGPIO_PIN_COUNT 17
#include "mcu/pcgpio_mcu.h"
#ifdef PCGPIO_SHOW_COMPILER_MESSAGES
......@@ -47,6 +49,7 @@
#elif defined(ARDUINO_AVR_UNO) || defined(ARDUINO_AVR_DUEMILANOVE)
#define PCGPIO_TARGET_ARCHITECTURE_ARDUINO_UNO
#define PCGPIO_GLOBAL_MCU_ID 0x0300
#define PCGPIO_PIN_COUNT 20
#include "mcu/pcgpio_mcu.h"
#ifdef PCGPIO_SHOW_COMPILER_MESSAGES
......@@ -57,6 +60,7 @@
#elif defined(ARDUINO_SAM_DUE)
#define PCGPIO_TARGET_ARCHITECTURE_ARDUINO_DUE
#define PCGPIO_GLOBAL_MCU_ID 0x0301
#define PCGPIO_PIN_COUNT 72
#include "mcu/pcgpio_mcu.h"
#ifdef PCGPIO_SHOW_COMPILER_MESSAGES
......@@ -67,6 +71,7 @@
#elif defined(ARDUINO_AVR_MEGA2560)
#define PCGPIO_TARGET_ARCHITECTURE_ARDUINO_MEGA
#define PCGPIO_GLOBAL_MCU_ID 0x0302
#define PCGPIO_PIN_COUNT 70
#include "mcu/pcgpio_mcu.h"
#ifdef PCGPIO_SHOW_COMPILER_MESSAGES
......@@ -78,6 +83,7 @@
#define PCGPIO_TARGET_ARCHITECTURE_ARDUINO_MEGA
#define PCGPIO_TARGET_ARCHITECTURE_ARGUINO_ADK
#define PCGPIO_GLOBAL_MCU_ID 0x0303
#define PCGPIO_PIN_COUNT 70
#include "mcu/pcgpio_mcu.h"
#ifdef PCGPIO_SHOW_COMPILER_MESSAGES
......
......@@ -23,10 +23,10 @@
#include "pcgpio_method.h"
#include "pcgpio_callback.h"
enum PCGPIO_PacketType {
PCGPIO_PACKETTYPE_METHOD = 0U,
PCGPIO_PACKETTYPE_CALLBACK = 1U
};
// enum PCGPIO_PacketType {
// PCGPIO_PACKETTYPE_METHOD = 0U,
// PCGPIO_PACKETTYPE_CALLBACK = 1U
// };
enum PCGPIO_Status {
PCGPIO_STATUS_OK = 0U,
......@@ -50,12 +50,12 @@ enum PCGPIO_PinConfig {
PCGPIO_PINCONFIG_DIGITALINPUT_RISINGCAPTURE = 0x04U,
PCGPIO_PINCONFIG_DIGITALINPUT_RISINGCAPTURE_PULLDOWN = 0x05U,
PCGPIO_PINCONFIG_DIGITALINPUT_RISINGCAPTURE_PULLUP = 0x06U,
PCGPIO_PINCONFIG_DIGITALINPUT_FALLINGCAPTURE = 0x07U,
PCGPIO_PINCONFIG_DIGITALINPUT_FALLINGCAPTURE_PULLDOWN = 0x08U,
PCGPIO_PINCONFIG_DIGITALINPUT_FALLINGCAPTURE_PULLUP = 0x09U,
PCGPIO_PINCONFIG_DIGITALINPUT_EDGECAPTURE = 0x0AU,
PCGPIO_PINCONFIG_DIGITALINPUT_EDGECAPTURE_PULLDOWN = 0x0BU,
PCGPIO_PINCONFIG_DIGITALINPUT_EDGECAPTURE_PULLUP = 0x0CU,
PCGPIO_PINCONFIG_DIGITALINPUT_FALLINGCAPTURE = 0x08U,
PCGPIO_PINCONFIG_DIGITALINPUT_FALLINGCAPTURE_PULLDOWN = 0x09U,
PCGPIO_PINCONFIG_DIGITALINPUT_FALLINGCAPTURE_PULLUP = 0x0AU,
PCGPIO_PINCONFIG_DIGITALINPUT_EDGECAPTURE = 0x0CU,
PCGPIO_PINCONFIG_DIGITALINPUT_EDGECAPTURE_PULLDOWN = 0x0DU,
PCGPIO_PINCONFIG_DIGITALINPUT_EDGECAPTURE_PULLUP = 0x0EU,
PCGPIO_PINCONFIG_DIGITALOUTPUT = 0x10,
PCGPIO_PINCONFIG_DIGITALOUTPUT_OPENDRAIN = 0x14,
......@@ -88,7 +88,8 @@ enum PCGPIO_PinConfig {
PCGPIO_PINCONFIG_ANALOGINPUT_14BIT = 0xF3,
PCGPIO_PINCONFIG_ANALOGINPUT_16BIT = 0xF4,
PCGPIO_PINCONFIG_ANALOGINPUT_20BIT = 0xF5,
PCGPIO_PINCONFIG_ANALOGINPUT_24BIT = 0xF6
PCGPIO_PINCONFIG_ANALOGINPUT_24BIT = 0xF6,
PCGPIO_PINCONFIG_ANALOGINPUT_32BIT = 0xF7
};
#endif
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