forked from mohr/ArduinoIO
new io bard file
This commit is contained in:
parent
51554fe4a6
commit
325f7c0bca
165
IOBoard.cpp
Normal file
165
IOBoard.cpp
Normal file
@ -0,0 +1,165 @@
|
||||
#include "IOBoard.h"
|
||||
#include <SPI.h>
|
||||
#include "ArduinoConfig.h"
|
||||
#include "helper/SimpleRingBuffer.h"
|
||||
#include "helper/DleEncoder.h"
|
||||
#include "helper/crc_ccitt.h"
|
||||
|
||||
SimpleRingBuffer ringBuffer(RING_BUFFER_SIZE, true);
|
||||
|
||||
uint8_t rawData[2 * RING_BUFFER_SIZE];
|
||||
size_t rawDataSize = 0;
|
||||
|
||||
namespace IOBoard {
|
||||
|
||||
void handleNewData() {
|
||||
ringBuffer.readData(rawData, sizeof(rawData), true, &rawDataSize);
|
||||
|
||||
if (rawDataSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//look for STX
|
||||
size_t firstSTXinRawData = 0;
|
||||
while ((firstSTXinRawData < rawDataSize)
|
||||
&& (rawData[firstSTXinRawData] != DleEncoder::STX)) {
|
||||
Serial.println(rawData[firstSTXinRawData]);
|
||||
firstSTXinRawData++;
|
||||
}
|
||||
|
||||
if (rawData[firstSTXinRawData] != DleEncoder::STX) {
|
||||
//there is no STX in our data, throw it away...
|
||||
Serial.println("NO STX");
|
||||
ringBuffer.deleteData(rawDataSize);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t packet[MAX_PACKET_LENGTH];
|
||||
size_t packetLen;
|
||||
|
||||
size_t readSize;
|
||||
|
||||
ReturnValue_t result = DleEncoder::decode(rawData + firstSTXinRawData,
|
||||
rawDataSize - firstSTXinRawData, &readSize, packet, sizeof(packet),
|
||||
&packetLen);
|
||||
|
||||
size_t toDelete = firstSTXinRawData;
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
handlePacket(packet, packetLen);
|
||||
|
||||
// after handling the packet, we can delete it from the raw stream,
|
||||
// it has been copied to packet
|
||||
toDelete += readSize;
|
||||
}
|
||||
|
||||
//remove Data which was processed
|
||||
ringBuffer.deleteData(toDelete);
|
||||
|
||||
}
|
||||
|
||||
void handlePacket(uint8_t *packet, size_t packetLen) {
|
||||
/* Paket layout is:
|
||||
------------------------------
|
||||
|byte | field |
|
||||
| | |
|
||||
|------------------------------|
|
||||
|1 | 8 bit command |
|
||||
|------------------------------|
|
||||
|1 | 8 bit address |
|
||||
|------------------------------|
|
||||
|2 | 16bit length |
|
||||
|------------------------------|
|
||||
|length | <length> byte data |
|
||||
|------------------------------|
|
||||
|2 | 16 bit crc |
|
||||
|------------------------------|
|
||||
------------------------------
|
||||
*/
|
||||
|
||||
uint16_t crc = Calculate_CRC(packet, packetLen);
|
||||
|
||||
if (crc != 0) {
|
||||
Serial.println("invalid Checksum");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t payloadLen = (packet[2] << 8) | packet[3];
|
||||
|
||||
if (payloadLen != packetLen - 6) {
|
||||
Serial.println("invalid len");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t command = packet[0];
|
||||
uint8_t address = packet[1];
|
||||
|
||||
switch (command) {
|
||||
case COMMAND_TRANSFER_SPI:
|
||||
transferSPI(address, packet + 4, payloadLen);
|
||||
//echo the data back, no need to change the header fields, they are the same
|
||||
//checksum will be written by sendReply()
|
||||
//check reply:
|
||||
Serial.println("Data response check: ");
|
||||
for(size_t i =0; i< packetLen; i++){
|
||||
Serial.print("packet nr ");Serial.print(i);Serial.print(" ");
|
||||
Serial.println(packet[i]);
|
||||
}
|
||||
sendReply(packet, packetLen);
|
||||
break;
|
||||
default:
|
||||
Serial.println("invalid command");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void transferSPI(uint8_t address, uint8_t *data, size_t datalen) {
|
||||
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE3));
|
||||
// The specified address is the bit where the last bit is port 0
|
||||
// and the first bit is port 7. It is inverted because the SPI protocol
|
||||
// requires the slave select to be driven low.
|
||||
CS_PORT = ~address;
|
||||
SPI.transfer(data, datalen);
|
||||
delay(100);
|
||||
// Pull the slave select high again.
|
||||
CS_PORT = 0xff;
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode and send the data, last two bytes of data are assumed to be for the checksum
|
||||
* and will be overwritten with it
|
||||
*/
|
||||
void sendReply(uint8_t *data, size_t len) {
|
||||
uint16_t crc = Calculate_CRC(data, len - 2);
|
||||
data[len - 2] = crc >> 8;
|
||||
data[len - 1] = crc;
|
||||
//we're being conservative here
|
||||
//TODO move this to global so other protocols can use it too
|
||||
uint8_t buffer[2 * len + 2];
|
||||
buffer[0] = DleEncoder::STX;
|
||||
size_t writtenLen;
|
||||
ReturnValue_t result = DleEncoder::encode(data, len, buffer, sizeof(buffer),
|
||||
&writtenLen, true);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
Serial.write(buffer, writtenLen);
|
||||
}
|
||||
|
||||
|
||||
//TODO check if this is thread safe by arduino
|
||||
void serialEvent() {
|
||||
//Serial.println(ringBuffer.availableWriteSpace());
|
||||
//uint8_t i = 0;
|
||||
|
||||
while (Serial.available()>0) {
|
||||
uint8_t byte = Serial.read();
|
||||
ringBuffer.writeData(&byte, 1);
|
||||
}
|
||||
//Serial.println(ringBuffer.availableWriteSpace());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
17
IOBoard.h
Normal file
17
IOBoard.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef IOBOARD_H_
|
||||
#define IOBOARD_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace IOBoard {
|
||||
|
||||
void handleNewData();
|
||||
void handlePacket(uint8_t *packet, size_t packetLen);
|
||||
void transferSPI(uint8_t address, uint8_t *data, size_t datalen);
|
||||
void sendReply(uint8_t *data, size_t len);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif /* IOBOARD_H_ */
|
186
main.cpp
186
main.cpp
@ -1,9 +1,7 @@
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "IOBoard.h"
|
||||
#include "ArduinoConfig.h"
|
||||
#include "helper/SimpleRingBuffer.h"
|
||||
#include "helper/DleEncoder.h"
|
||||
#include "helper/crc_ccitt.h"
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
@ -11,178 +9,28 @@
|
||||
//from the core and we need to include it explicitly
|
||||
#include <SPI.h>
|
||||
|
||||
SimpleRingBuffer ringBuffer(RING_BUFFER_SIZE, true);
|
||||
|
||||
uint8_t rawData[2 * RING_BUFFER_SIZE];
|
||||
size_t rawDataSize = 0;
|
||||
|
||||
/**
|
||||
* Encode and send the data, last two bytes of data are assumed to be for the checksum
|
||||
* and will be overwritten with it
|
||||
*/
|
||||
void sendData(uint8_t *data, size_t len) {
|
||||
uint16_t crc = Calculate_CRC(data, len - 2);
|
||||
data[len - 2] = crc >> 8;
|
||||
data[len - 1] = crc;
|
||||
//we're being conservative here
|
||||
//TODO move this to global so other protocols can use it too
|
||||
uint8_t buffer[2 * len + 2];
|
||||
buffer[0] = DleEncoder::STX;
|
||||
size_t writtenLen;
|
||||
ReturnValue_t result = DleEncoder::encode(data, len, buffer, sizeof(buffer),
|
||||
&writtenLen, true);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return;
|
||||
}
|
||||
Serial.write(buffer, writtenLen);
|
||||
}
|
||||
|
||||
void transferSPI(uint8_t address, uint8_t *data, size_t datalen) {
|
||||
SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE3));
|
||||
// The specified address is the bit where the last bit is port 0
|
||||
// and the first bit is port 7. It is inverted because the SPI protocol
|
||||
// requires the slave select to be driven low.
|
||||
CS_PORT = ~address;
|
||||
SPI.transfer(data, datalen);
|
||||
delay(100);
|
||||
// Pull the slave select high again.
|
||||
CS_PORT = 0xff;
|
||||
SPI.endTransaction();
|
||||
|
||||
}
|
||||
|
||||
void handlePacket(uint8_t *packet, size_t packetLen) {
|
||||
/* Paket layout is:
|
||||
------------------------------
|
||||
|byte | field |
|
||||
| | |
|
||||
|------------------------------|
|
||||
|1 | 8 bit command |
|
||||
|------------------------------|
|
||||
|1 | 8 bit address |
|
||||
|------------------------------|
|
||||
|2 | 16bit length |
|
||||
|------------------------------|
|
||||
|length | <length> byte data |
|
||||
|------------------------------|
|
||||
|2 | 16 bit crc |
|
||||
|------------------------------|
|
||||
------------------------------
|
||||
*/
|
||||
|
||||
uint16_t crc = Calculate_CRC(packet, packetLen);
|
||||
|
||||
if (crc != 0) {
|
||||
Serial.println("invalid Checksum");
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t payloadLen = (packet[2] << 8) | packet[3];
|
||||
|
||||
if (payloadLen != packetLen - 6) {
|
||||
Serial.println("invalid len");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t command = packet[0];
|
||||
uint8_t address = packet[1];
|
||||
|
||||
switch (command) {
|
||||
case COMMAND_TRANSFER_SPI:
|
||||
transferSPI(address, packet + 4, payloadLen);
|
||||
//echo the data back, no need to change the header fields, they are the same
|
||||
//checksum will be written by sendData()
|
||||
//check reply:
|
||||
Serial.println("Data response check: ");
|
||||
for(size_t i =0; i< packetLen; i++){
|
||||
Serial.print("packet nr ");Serial.print(i);Serial.print(" ");
|
||||
Serial.println(packet[i]);
|
||||
}
|
||||
sendData(packet, packetLen);
|
||||
break;
|
||||
default:
|
||||
Serial.println("invalid command");
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void handleNewData() {
|
||||
ringBuffer.readData(rawData, sizeof(rawData), true, &rawDataSize);
|
||||
|
||||
if (rawDataSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
//look for STX
|
||||
size_t firstSTXinRawData = 0;
|
||||
while ((firstSTXinRawData < rawDataSize)
|
||||
&& (rawData[firstSTXinRawData] != DleEncoder::STX)) {
|
||||
Serial.println(rawData[firstSTXinRawData]);
|
||||
firstSTXinRawData++;
|
||||
}
|
||||
|
||||
if (rawData[firstSTXinRawData] != DleEncoder::STX) {
|
||||
//there is no STX in our data, throw it away...
|
||||
Serial.println("NO STX");
|
||||
ringBuffer.deleteData(rawDataSize);
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t packet[MAX_PACKET_LENGTH];
|
||||
size_t packetLen;
|
||||
|
||||
size_t readSize;
|
||||
|
||||
ReturnValue_t result = DleEncoder::decode(rawData + firstSTXinRawData,
|
||||
rawDataSize - firstSTXinRawData, &readSize, packet, sizeof(packet),
|
||||
&packetLen);
|
||||
|
||||
size_t toDelete = firstSTXinRawData;
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
handlePacket(packet, packetLen);
|
||||
|
||||
// after handling the packet, we can delete it from the raw stream,
|
||||
// it has been copied to packet
|
||||
toDelete += readSize;
|
||||
}
|
||||
|
||||
//remove Data which was processed
|
||||
ringBuffer.deleteData(toDelete);
|
||||
|
||||
}
|
||||
|
||||
//TODO check if this is thread safe by arduino
|
||||
void serialEvent() {
|
||||
//Serial.println(ringBuffer.availableWriteSpace());
|
||||
//uint8_t i = 0;
|
||||
|
||||
while (Serial.available()>0) {
|
||||
uint8_t byte = Serial.read();
|
||||
ringBuffer.writeData(&byte, 1);
|
||||
}
|
||||
//Serial.println(ringBuffer.availableWriteSpace());
|
||||
}
|
||||
|
||||
void setup() {
|
||||
// Set data direction of selected port to output.
|
||||
CS_DDR = 0xff;
|
||||
// Drive all the slave selects high as required for the SPI protocol
|
||||
// if no transfer is going on.
|
||||
CS_PORT = 0xff;
|
||||
Serial.begin(BAUD_RATE);
|
||||
CS_DDR = 0xff;
|
||||
// Drive all the slave selects high as required for the SPI protocol
|
||||
// if no transfer is going on.
|
||||
CS_PORT = 0xff;
|
||||
Serial.begin(BAUD_RATE);
|
||||
#if PROGRAMMING_OUTPUT == 1
|
||||
Serial.println("-AI- Setting up Arduino IO interface board.");
|
||||
Serial.print("-AI- Configured baud rate for serial communication: ");
|
||||
Serial.println(BAUD_RATE, DEC);
|
||||
Serial.print("-AI- Size of serial receiver buffer: ");
|
||||
Serial.print(SERIAL_RX_BUFFER_SIZE, DEC);
|
||||
Serial.println(" bytes");
|
||||
Serial.println("-AI- Setting up Arduino IO interface board.");
|
||||
Serial.print("-AI- Configured baud rate for serial communication: ");
|
||||
Serial.println(BAUD_RATE, DEC);
|
||||
Serial.print("-AI- Size of serial receiver buffer: ");
|
||||
Serial.print(SERIAL_RX_BUFFER_SIZE, DEC);
|
||||
Serial.println(" bytes");
|
||||
#endif
|
||||
SPI.begin();
|
||||
SPI.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
handleNewData();
|
||||
delay(1000);
|
||||
IOBoard::handleNewData();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user