aboutsummaryrefslogtreecommitdiff
path: root/libraries/WiFi/utility/spi_drv.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/WiFi/utility/spi_drv.cpp')
-rw-r--r--libraries/WiFi/utility/spi_drv.cpp506
1 files changed, 506 insertions, 0 deletions
diff --git a/libraries/WiFi/utility/spi_drv.cpp b/libraries/WiFi/utility/spi_drv.cpp
new file mode 100644
index 0000000..12a320b
--- /dev/null
+++ b/libraries/WiFi/utility/spi_drv.cpp
@@ -0,0 +1,506 @@
+
+#include "Arduino.h"
+#include "spi_drv.h"
+#include "pins_arduino.h"
+//#define _DEBUG_
+extern "C" {
+#include "debug.h"
+}
+
+#define DATAOUT 11 // MOSI
+#define DATAIN 12 // MISO
+#define SPICLOCK 13 // sck
+#define SLAVESELECT 10 // ss
+#define SLAVEREADY 7 // handshake pin
+#define WIFILED 9 // led on wifi shield
+
+#define DELAY_100NS do { asm volatile("nop"); }while(0);
+#define DELAY_SPI(X) { int ii=0; do { asm volatile("nop"); }while(++ii<X);}
+#define DELAY_TRANSFER() DELAY_SPI(10)
+
+void SpiDrv::begin()
+{
+ // Set direction register for SCK and MOSI pin.
+ // MISO pin automatically overrides to INPUT.
+ // When the SS pin is set as OUTPUT, it can be used as
+ // a general purpose output port (it doesn't influence
+ // SPI operations).
+
+ pinMode(SCK, OUTPUT);
+ pinMode(MOSI, OUTPUT);
+ pinMode(SS, OUTPUT);
+ pinMode(SLAVESELECT, OUTPUT);
+ pinMode(SLAVEREADY, INPUT);
+ pinMode(WIFILED, OUTPUT);
+
+ digitalWrite(SCK, LOW);
+ digitalWrite(MOSI, LOW);
+ digitalWrite(SS, HIGH);
+ digitalWrite(SLAVESELECT, HIGH);
+ digitalWrite(WIFILED, LOW);
+
+#ifdef _DEBUG_
+ INIT_TRIGGER()
+#endif
+
+ // Warning: if the SS pin ever becomes a LOW INPUT then SPI
+ // automatically switches to Slave, so the data direction of
+ // the SS pin MUST be kept as OUTPUT.
+ SPCR |= _BV(MSTR);
+ SPCR |= _BV(SPE);
+ //SPSR |= _BV(SPI2X);
+}
+
+void SpiDrv::end() {
+ SPCR &= ~_BV(SPE);
+}
+
+void SpiDrv::spiSlaveSelect()
+{
+ digitalWrite(SLAVESELECT,LOW);
+}
+
+
+void SpiDrv::spiSlaveDeselect()
+{
+ digitalWrite(SLAVESELECT,HIGH);
+}
+
+void delaySpi()
+{
+ int i = 0;
+ const int DELAY = 1000;
+ for (;i<DELAY;++i)
+ {
+ int a =a+1;
+ }
+}
+
+char SpiDrv::spiTransfer(volatile char data)
+{
+ SPDR = data; // Start the transmission
+ while (!(SPSR & (1<<SPIF))) // Wait the end of the transmission
+ {
+ };
+ char result = SPDR;
+ DELAY_TRANSFER();
+
+ return result; // return the received byte
+}
+
+int SpiDrv::waitSpiChar(unsigned char waitChar)
+{
+ int timeout = TIMEOUT_CHAR;
+ unsigned char _readChar = 0;
+ do{
+ _readChar = readChar(); //get data byte
+ if (_readChar == ERR_CMD)
+ {
+ WARN("Err cmd received\n");
+ return -1;
+ }
+ }while((timeout-- > 0) && (_readChar != waitChar));
+ return (_readChar == waitChar);
+}
+
+int SpiDrv::readAndCheckChar(char checkChar, char* readChar)
+{
+ getParam((uint8_t*)readChar);
+
+ return (*readChar == checkChar);
+}
+
+char SpiDrv::readChar()
+{
+ uint8_t readChar = 0;
+ getParam(&readChar);
+ return readChar;
+}
+
+#define WAIT_START_CMD(x) waitSpiChar(START_CMD)
+
+#define IF_CHECK_START_CMD(x) \
+ if (!WAIT_START_CMD(_data)) \
+ { \
+ TOGGLE_TRIGGER() \
+ WARN("Error waiting START_CMD"); \
+ return 0; \
+ }else \
+
+#define CHECK_DATA(check, x) \
+ if (!readAndCheckChar(check, &x)) \
+ { \
+ TOGGLE_TRIGGER() \
+ WARN("Reply error"); \
+ INFO2(check, (uint8_t)x); \
+ return 0; \
+ }else \
+
+#define waitSlaveReady() (digitalRead(SLAVEREADY) == LOW)
+#define waitSlaveSign() (digitalRead(SLAVEREADY) == HIGH)
+#define waitSlaveSignalH() while(digitalRead(SLAVEREADY) != HIGH){}
+#define waitSlaveSignalL() while(digitalRead(SLAVEREADY) != LOW){}
+
+void SpiDrv::waitForSlaveSign()
+{
+ while (!waitSlaveSign());
+}
+
+void SpiDrv::waitForSlaveReady()
+{
+ while (!waitSlaveReady());
+}
+
+void SpiDrv::getParam(uint8_t* param)
+{
+ // Get Params data
+ *param = spiTransfer(DUMMY_DATA);
+ DELAY_TRANSFER();
+}
+
+int SpiDrv::waitResponseCmd(uint8_t cmd, uint8_t numParam, uint8_t* param, uint8_t* param_len)
+{
+ char _data = 0;
+ int ii = 0;
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ CHECK_DATA(numParam, _data);
+ {
+ readParamLen8(param_len);
+ for (ii=0; ii<(*param_len); ++ii)
+ {
+ // Get Params data
+ //param[ii] = spiTransfer(DUMMY_DATA);
+ getParam(&param[ii]);
+ }
+ }
+
+ readAndCheckChar(END_CMD, &_data);
+ }
+
+ return 1;
+}
+/*
+int SpiDrv::waitResponse(uint8_t cmd, uint8_t numParam, uint8_t* param, uint16_t* param_len)
+{
+ char _data = 0;
+ int i =0, ii = 0;
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ CHECK_DATA(numParam, _data);
+ {
+ readParamLen16(param_len);
+ for (ii=0; ii<(*param_len); ++ii)
+ {
+ // Get Params data
+ param[ii] = spiTransfer(DUMMY_DATA);
+ }
+ }
+
+ readAndCheckChar(END_CMD, &_data);
+ }
+
+ return 1;
+}
+*/
+
+int SpiDrv::waitResponseData16(uint8_t cmd, uint8_t* param, uint16_t* param_len)
+{
+ char _data = 0;
+ uint16_t ii = 0;
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ uint8_t numParam = readChar();
+ if (numParam != 0)
+ {
+ readParamLen16(param_len);
+ for (ii=0; ii<(*param_len); ++ii)
+ {
+ // Get Params data
+ param[ii] = spiTransfer(DUMMY_DATA);
+ }
+ }
+
+ readAndCheckChar(END_CMD, &_data);
+ }
+
+ return 1;
+}
+
+int SpiDrv::waitResponseData8(uint8_t cmd, uint8_t* param, uint8_t* param_len)
+{
+ char _data = 0;
+ int ii = 0;
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ uint8_t numParam = readChar();
+ if (numParam != 0)
+ {
+ readParamLen8(param_len);
+ for (ii=0; ii<(*param_len); ++ii)
+ {
+ // Get Params data
+ param[ii] = spiTransfer(DUMMY_DATA);
+ }
+ }
+
+ readAndCheckChar(END_CMD, &_data);
+ }
+
+ return 1;
+}
+
+int SpiDrv::waitResponseParams(uint8_t cmd, uint8_t numParam, tParam* params)
+{
+ char _data = 0;
+ int i =0, ii = 0;
+
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ uint8_t _numParam = readChar();
+ if (_numParam != 0)
+ {
+ for (i=0; i<_numParam; ++i)
+ {
+ params[i].paramLen = readParamLen8();
+ for (ii=0; ii<params[i].paramLen; ++ii)
+ {
+ // Get Params data
+ params[i].param[ii] = spiTransfer(DUMMY_DATA);
+ }
+ }
+ } else
+ {
+ WARN("Error numParam == 0");
+ return 0;
+ }
+
+ if (numParam != _numParam)
+ {
+ WARN("Mismatch numParam");
+ return 0;
+ }
+
+ readAndCheckChar(END_CMD, &_data);
+ }
+ return 1;
+}
+
+/*
+int SpiDrv::waitResponse(uint8_t cmd, tParam* params, uint8_t* numParamRead, uint8_t maxNumParams)
+{
+ char _data = 0;
+ int i =0, ii = 0;
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ uint8_t numParam = readChar();
+
+ if (numParam > maxNumParams)
+ {
+ numParam = maxNumParams;
+ }
+ *numParamRead = numParam;
+ if (numParam != 0)
+ {
+ for (i=0; i<numParam; ++i)
+ {
+ params[i].paramLen = readParamLen8();
+
+ for (ii=0; ii<params[i].paramLen; ++ii)
+ {
+ // Get Params data
+ params[i].param[ii] = spiTransfer(DUMMY_DATA);
+ }
+ }
+ } else
+ {
+ WARN("Error numParams == 0");
+ Serial.println(cmd, 16);
+ return 0;
+ }
+ readAndCheckChar(END_CMD, &_data);
+ }
+ return 1;
+}
+*/
+
+int SpiDrv::waitResponse(uint8_t cmd, uint8_t* numParamRead, uint8_t** params, uint8_t maxNumParams)
+{
+ char _data = 0;
+ int i =0, ii = 0;
+
+ char *index[WL_SSID_MAX_LENGTH];
+
+ for (i = 0 ; i < WL_NETWORKS_LIST_MAXNUM ; i++)
+ index[i] = (char *)params + WL_SSID_MAX_LENGTH*i;
+
+ IF_CHECK_START_CMD(_data)
+ {
+ CHECK_DATA(cmd | REPLY_FLAG, _data){};
+
+ uint8_t numParam = readChar();
+
+ if (numParam > maxNumParams)
+ {
+ numParam = maxNumParams;
+ }
+ *numParamRead = numParam;
+ if (numParam != 0)
+ {
+ for (i=0; i<numParam; ++i)
+ {
+ uint8_t paramLen = readParamLen8();
+ for (ii=0; ii<paramLen; ++ii)
+ {
+ //ssid[ii] = spiTransfer(DUMMY_DATA);
+ // Get Params data
+ index[i][ii] = (uint8_t)spiTransfer(DUMMY_DATA);
+
+ }
+ index[i][ii]=0;
+ }
+ } else
+ {
+ WARN("Error numParams == 0");
+ readAndCheckChar(END_CMD, &_data);
+ return 0;
+ }
+ readAndCheckChar(END_CMD, &_data);
+ }
+ return 1;
+}
+
+
+void SpiDrv::sendParam(uint8_t* param, uint8_t param_len, uint8_t lastParam)
+{
+ int i = 0;
+ // Send Spi paramLen
+ sendParamLen8(param_len);
+
+ // Send Spi param data
+ for (i=0; i<param_len; ++i)
+ {
+ spiTransfer(param[i]);
+ }
+
+ // if lastParam==1 Send Spi END CMD
+ if (lastParam == 1)
+ spiTransfer(END_CMD);
+}
+
+void SpiDrv::sendParamLen8(uint8_t param_len)
+{
+ // Send Spi paramLen
+ spiTransfer(param_len);
+}
+
+void SpiDrv::sendParamLen16(uint16_t param_len)
+{
+ // Send Spi paramLen
+ spiTransfer((uint8_t)((param_len & 0xff00)>>8));
+ spiTransfer((uint8_t)(param_len & 0xff));
+}
+
+uint8_t SpiDrv::readParamLen8(uint8_t* param_len)
+{
+ uint8_t _param_len = spiTransfer(DUMMY_DATA);
+ if (param_len != NULL)
+ {
+ *param_len = _param_len;
+ }
+ return _param_len;
+}
+
+uint16_t SpiDrv::readParamLen16(uint16_t* param_len)
+{
+ uint16_t _param_len = spiTransfer(DUMMY_DATA)<<8 | (spiTransfer(DUMMY_DATA)& 0xff);
+ if (param_len != NULL)
+ {
+ *param_len = _param_len;
+ }
+ return _param_len;
+}
+
+
+void SpiDrv::sendBuffer(uint8_t* param, uint16_t param_len, uint8_t lastParam)
+{
+ uint16_t i = 0;
+
+ // Send Spi paramLen
+ sendParamLen16(param_len);
+
+ // Send Spi param data
+ for (i=0; i<param_len; ++i)
+ {
+ spiTransfer(param[i]);
+ }
+
+ // if lastParam==1 Send Spi END CMD
+ if (lastParam == 1)
+ spiTransfer(END_CMD);
+}
+
+
+void SpiDrv::sendParam(uint16_t param, uint8_t lastParam)
+{
+ // Send Spi paramLen
+ sendParamLen8(2);
+
+ spiTransfer((uint8_t)((param & 0xff00)>>8));
+ spiTransfer((uint8_t)(param & 0xff));
+
+ // if lastParam==1 Send Spi END CMD
+ if (lastParam == 1)
+ spiTransfer(END_CMD);
+}
+
+/* Cmd Struct Message */
+/* _________________________________________________________________________________ */
+/*| START CMD | C/R | CMD |[TOT LEN]| N.PARAM | PARAM LEN | PARAM | .. | END CMD | */
+/*|___________|______|______|_________|_________|___________|________|____|_________| */
+/*| 8 bit | 1bit | 7bit | 8bit | 8bit | 8bit | nbytes | .. | 8bit | */
+/*|___________|______|______|_________|_________|___________|________|____|_________| */
+
+void SpiDrv::sendCmd(uint8_t cmd, uint8_t numParam)
+{
+ // Send Spi START CMD
+ spiTransfer(START_CMD);
+
+ //waitForSlaveSign();
+ //wait the interrupt trigger on slave
+ delayMicroseconds(SPI_START_CMD_DELAY);
+
+ // Send Spi C + cmd
+ spiTransfer(cmd & ~(REPLY_FLAG));
+
+ // Send Spi totLen
+ //spiTransfer(totLen);
+
+ // Send Spi numParam
+ spiTransfer(numParam);
+
+ // If numParam == 0 send END CMD
+ if (numParam == 0)
+ spiTransfer(END_CMD);
+
+}
+
+SpiDrv spiDrv;