-
-
Save shaielc/e0937d68978b03b2544474b641328145 to your computer and use it in GitHub Desktop.
| #include<SlaveSPIClass.h> | |
| int SlaveSPI::size = 0; | |
| SlaveSPI** SlaveSPI::SlaveSPIVector = NULL; | |
| void setupIntr(spi_slave_transaction_t * trans) | |
| { | |
| for(int i=0 ; i<SlaveSPI::size;i++) | |
| { | |
| if(SlaveSPI::SlaveSPIVector[i]->match(trans)) | |
| SlaveSPI::SlaveSPIVector[i]->setup_intr(trans); | |
| } | |
| } | |
| void transIntr(spi_slave_transaction_t * trans) | |
| { | |
| for(int i=0 ; i<SlaveSPI::size;i++) | |
| { | |
| if(SlaveSPI::SlaveSPIVector[i]->match(trans)) | |
| SlaveSPI::SlaveSPIVector[i]->trans_intr(trans); | |
| } | |
| } | |
| SlaveSPI::SlaveSPI() | |
| { | |
| SlaveSPI** temp = new SlaveSPI * [size+1]; | |
| for (int i=0;i<size;i++) | |
| { | |
| temp[i]=SlaveSPIVector[i]; | |
| } | |
| temp[size] = this; | |
| size++; | |
| delete [] SlaveSPIVector; | |
| SlaveSPIVector = temp; | |
| buff = ""; | |
| transBuffer = ""; | |
| } | |
| void SlaveSPI::begin(gpio_num_t so,gpio_num_t si,gpio_num_t sclk,gpio_num_t ss,size_t length,void(* ext)()) | |
| { | |
| //should set to the minimum transaction length | |
| t_size = length; | |
| driver = new spi_slave_transaction_t{t_size * 8 , 0 , heap_caps_malloc(max(t_size,32), MALLOC_CAP_DMA), heap_caps_malloc(max(t_size,32), MALLOC_CAP_DMA),NULL}; | |
| spi_bus_config_t buscfg={ | |
| .mosi_io_num=si, | |
| .miso_io_num=so, | |
| .sclk_io_num=sclk | |
| }; | |
| gpio_set_pull_mode(sclk, GPIO_PULLUP_ONLY); | |
| gpio_set_pull_mode(ss, GPIO_PULLUP_ONLY); | |
| spi_slave_interface_config_t slvcfg={ss,0,1,0,setupIntr,transIntr};//check the IDF for further explenation | |
| spi_slave_initialize(HSPI_HOST, &buscfg, &slvcfg,1); //DMA channel 1 | |
| spi_slave_queue_trans(HSPI_HOST,driver,portMAX_DELAY);//ready for input (no transmit) | |
| exter_intr =ext; | |
| } | |
| void SlaveSPI::setup_intr(spi_slave_transaction_t *trans) | |
| {//called when the trans is set in the queue | |
| //didn't find use for it in the end. | |
| } | |
| void SlaveSPI::trans_intr(spi_slave_transaction_t *trans) | |
| {//called when the trans has finished | |
| for(int i=0;i<(driver->trans_len/8);i++) | |
| { | |
| buff += ((char*)driver->rx_buffer)[i]; | |
| ((char*) driver->rx_buffer)[i] = (char)0; | |
| size++; | |
| } | |
| setDriver(); | |
| exter_intr(); | |
| } | |
| void SlaveSPI::trans_queue(String& transmission){ | |
| //used to queue data to transmit | |
| for (int i=0;i<transmission.length();i++) | |
| transBuffer += transmission[i]; | |
| } | |
| inline bool SlaveSPI::match(spi_slave_transaction_t * trans) | |
| { | |
| return (this->driver == trans); | |
| } | |
| void SlaveSPI::setDriver() | |
| { | |
| driver->user = NULL; | |
| int i=0; | |
| for(;i<(driver->trans_len/8)&&i<transBuffer.length();i++) | |
| { | |
| ((char*) driver->tx_buffer)[i] = transBuffer[i]; | |
| } | |
| transBuffer = &(transBuffer[i]); | |
| driver->length=t_size*8; | |
| driver->trans_len = 0; | |
| spi_slave_queue_trans(HSPI_HOST,driver,portMAX_DELAY); | |
| } | |
| char SlaveSPI::read() | |
| { | |
| char temp = buff[0]; | |
| buff.remove(0,1); | |
| size--; | |
| return temp; | |
| } | |
| #ifndef SLAVE_SPI_CLASS | |
| #define SLAVE_SPI_CLASS | |
| #include "Arduino.h" | |
| #include "driver/spi_slave.h" | |
| void setupIntr(spi_slave_transaction_t * trans); | |
| void transIntr(spi_slave_transaction_t * trans); | |
| class SlaveSPI | |
| { | |
| static SlaveSPI** SlaveSPIVector; | |
| static int size; | |
| friend void setupIntr(spi_slave_transaction_t * trans); | |
| friend void transIntr(spi_slave_transaction_t * trans); | |
| String buff;//used to save incoming data | |
| String transBuffer;//used to buffer outgoing data !not tested! | |
| spi_slave_transaction_t * driver; | |
| void (*exter_intr)();//interrupt at the end of transmission , if u need to do something at the end of each transmission | |
| size_t t_size;//length of transaction buffer, (should be set to maximum transition size) | |
| public: | |
| SlaveSPI(); | |
| int size; | |
| void setup_intr(spi_slave_transaction_t *trans);//called when the trans is set in the queue | |
| void trans_intr(spi_slave_transaction_t *trans);//called when the trans has finished | |
| void begin(gpio_num_t so,gpio_num_t si,gpio_num_t sclk,gpio_num_t ss,size_t length=128,void(* ext)() = NULL); | |
| void trans_queue(String& transmission);//used to queue data to transmit | |
| inline char* operator[](int i){return (&buff[i]);} | |
| inline void flush(){buff = "";size=0;} | |
| inline bool match(spi_slave_transaction_t * trans); | |
| void setDriver(); | |
| char read(); | |
| inline String* getBuff(){return &buff;} | |
| }; | |
| #endif |
| #include <SlaveSPIClass.h> | |
| #include <SPI.h> | |
| #define MO 22 | |
| #define MI 23 | |
| #define MCLK 19 | |
| #define MS 18 | |
| #define SO 32 | |
| #define SI 25 | |
| #define SCLK 27 | |
| #define SS 34 | |
| SlaveSPI slave; | |
| SPIClass master(VSPI); | |
| void test(); | |
| void setup() { | |
| Serial.begin(115200); | |
| // put your setup code here, to run once: | |
| master.begin(MCLK,MI,MO); | |
| slave.begin((gpio_num_t)SO,(gpio_num_t)SI,(gpio_num_t)SCLK,(gpio_num_t)SS,8,test);//seems to work with groups of 4 bytes | |
| SPI.beginTransaction(SPISettings(14000000, MSBFIRST, SPI_MODE0)); | |
| pinMode(MS,OUTPUT); | |
| } | |
| String txt = ""; | |
| String cmd =""; | |
| void loop() { | |
| // put your main code here, to run repeatedly: | |
| if(slave.getBuff()->length()&&digitalRead(SS)==HIGH) | |
| { | |
| while(slave.getBuff()->length()) | |
| txt+=slave.read(); | |
| Serial.println("slave input:"); | |
| Serial.println(txt); | |
| } | |
| while(Serial.available()) | |
| { | |
| cmd +=(char) Serial.read(); | |
| } | |
| while(txt.length()>0) | |
| { | |
| slave.trans_queue(txt); | |
| Serial.println("slave output:"); | |
| Serial.println(txt); | |
| txt =""; | |
| } | |
| while(cmd.length()>0) | |
| { | |
| Serial.println("input:"); | |
| Serial.println(cmd); | |
| Serial.println("Master input:"); | |
| digitalWrite(MS,LOW); | |
| for(int i=0;i<cmd.length();i++) | |
| { | |
| cmd[i] = master.transfer(cmd[i]); //ERROR : gives the transmitted data <<1 | |
| } | |
| digitalWrite(MS,HIGH); | |
| for(int i=0;i<cmd.length();i++) | |
| Serial.print(cmd[i],HEX); | |
| cmd =""; | |
| } | |
| } | |
| void test() | |
| { | |
| //Serial.println("test"); | |
| //Serial.println(slave[0]); | |
| } | |
I feel like something else is wrong with size and size_.
Fix #3
It does not make sense that an instance value is used in the constructor SlaveSPI::SlaveSPI() because size is only used to affect the static member SlaveSPIVector.
SlaveSPIClass.cpp @ lines 20 to 33: replace every size with SlaveSPI::size_.
Possible fix
The instance's size is not explicitly initialized. It looks like a buffer count. It should probably be initialized to 0 in the member initialization part of the constructor. The default value is to be checked.
EDIT #1
Yes! My fixes #1 to #3 made it work somehow! I was receiving nothing at all without the fix #3. Now I'm receiving a corrupted message but at least I have a correct piece of it.
I am using platform IO, and after implementing all the fixes above, I cannot compile:
My error is inline 29 of .cpp file: tx_buffer = (uint8_t *)heap_caps_malloc(max(max_buffer_size, 32), SPI_MALLOC_CAP);
the error is: no instance of max(size_t,int)
any help or suggestions?
Hey there,
I could fix the compile errors and warnings, which turned out to be just 2 tiny problems.
At the moment I do not know if it makes the program work.
Fix #1
The same name is used for a static member and an instance member.
In SlaveSPIClass.h @ line 2
becomes
In SlaveSPIClass.cpp @ lines 2, 6, 14: replace occurrences of
SlaveSPI::sizewithSlaveSPI::size_.Fix #2
The compiler messes up the implicit conversion from integer literal to
t_size.SlaveSPIClass.cpp @ line 41
becomes