Hi,
This follow my previous post SPI communication between Uno and Pro mini problem
after looking around and some tinkering with the code I finally got it to work!
MASTER code:
#include <SPI.h>
volatile char req[9];
volatile uint8_t a,i=0;
byte transferAndWait (const byte what)
{
 byte x = SPI.transfer (what);
 delayMicroseconds (20); //wait for slave to process and reply
 return x;
}
void setup (void)
{
 Serial.begin (9600);
Â
 digitalWrite(SS, HIGH); // ensure SS stays high for now
 SPI.begin ();
 SPI.beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0));
Â
 Serial.println ("READY");
}
void loop (void)
{
uint8_t j;
 if(Serial.available()){
  req[i] = Serial.read();
  ++i;
 }
Â
 if(req[i-1]==';'){
   if(req[0]=='o'){ //turn LED OFF
    // enable Slave Select
    digitalWrite(SS, LOW);
    a = transferAndWait(0); //start SPI COMMS
    //Serial.println (String(a,HEX));
    a = transferAndWait('o'); //send command
    //Serial.println (String(a,HEX));
    a = transferAndWait(0); //end SPI COMMS
   Â
    if(a == 'O'){
     Serial.print("LED OFF!");
     Serial.println (char(a));    Â
    }
    else{
     Serial.print("Failed! ");
     Serial.println (String(a,HEX));
     while(a!=0) a = transferAndWait(0); //reset comms
    }
  Â
    // disable Slave Select
    digitalWrite(SS, HIGH);
   }
   else if(req[0]=='i'){ //turn LED ON
    // enable Slave Select
    digitalWrite(SS, LOW);
    a = transferAndWait(0); //start SPI COMMS
    //Serial.println (String(a,HEX));
    a = transferAndWait('i'); //send command
    //Serial.println (String(a,HEX));
    a = transferAndWait(0); //end SPI COMMS
      Â
    if(a == 'I'){
     Serial.print("LED ON!");
     Serial.println (char(a));
    }
    else{
     Serial.print("Failed! ");
     Serial.println (String(a,HEX));
     while(a!=0) a = transferAndWait(0); //reset comms
    }
       Â
    // disable Slave Select
    digitalWrite(SS, HIGH);
   }
   else if(req[0]=='b'){ //blink LED with 50% duty
    // enable Slave Select
    digitalWrite(SS, LOW);
    a = transferAndWait(0); //start SPI COMMS
    //Serial.println (String(a,HEX));
    a = transferAndWait('b'); //send command
    //Serial.println (String(a,HEX));
   Â
    j=i-2; //get number of data bytes
    a = transferAndWait(j); //send number of data bytes
    //Serial.println (String(a,HEX));
    Â
    for(j=1; j<i;++j){
     a = transferAndWait(req[j]); //send data bytes
     //Serial.println (String(a,HEX));       Â
    }
    a = transferAndWait(0); //end SPI COMMS
    if(a == 'B'){
     Serial.print("LED Blinking!");
     Serial.println (char(a));
    }
    else{
     Serial.print("Failed! ");
     Serial.println (String(a,HEX));
     while(a!=0) a = transferAndWait(0); //reset comms
    }
   }
  Â
   i=0;
 }
}
SLAVE code:
#define TGL_BIT(x,y) ((x)^=(1<<(y))) //toggle bit y in byte x
#include <SPI.h>
volatile uint8_t start=0,command=0, blink_en=0,i=0,n;
uint8_t T_char[5]={0};
volatile uint16_t T;
volatile long oldtime=0;
// SPI interrupt routine
ISR (SPI_STC_vect)
{Â
 byte spi = SPDR;
 if(spi==0 && start==0){ //start of SPI comms
  if(command!=0xA3){
   start=1;
   SPDR = 0xA4; //acknowledge start of comms
  }
  else{
   command=0;
   SPDR = 0;
  }
 }
 else if(start>0){
   if(start==1){
    command = spi;
    start=2;
   }
 Â
   switch (command)
   {
    case 'o':
     digitalWrite(2,LOW);
     SPDR = 'O';
     command = 0xA3; //end of command
     blink_en=0; //disable LED blinking
     start=0; //end of comms
    break;
    case 'i':
     digitalWrite(2,HIGH);
     SPDR = 'I';
     command = 0xA3; //end of command
     blink_en=0; //disable LED blinking
     start=0; //end of comms
    break;
    case 'b':
     if(i==0){ //command byte received
      i=1;
      SPDR = 0xA5;
     }
     else if(i==1){
      n=spi; //number of data bytes
      i=2;
      SPDR = spi|0xA0;
     }
     else if(i-2<n){//received data bytes
      T_char[i-2]=spi;
      ++i;
      SPDR = spi|0xA0; Â
     }
     else if(i-2==n){ //evalute period from data bytes
      T_char[n]='\0';
      T = atoi( T_char);
      T/=2;
      i=0; //reset counter
      blink_en=1; //enable LED blinking
      command = 0xA3; //end of command
      start=0; //end of comms
      SPDR = 'B';
     }
    break;
   }
 }
}
void setup (void)
{
 pinMode(2, OUTPUT); //LED output
 digitalWrite(2,LOW);
Â
 // have to send on master in, *slave out*
 pinMode(MISO, OUTPUT);
 // turn on SPI in slave mode
 SPCR |= _BV(SPE);
 // turn on interrupts
 SPCR |= _BV(SPIE);
 SPDR = 0; //initialise SPI register
Â
}Â // end of setup
void loop (void)
{
 if(blink_en==1 && ((millis()-oldtime)>T)){
  oldtime=millis();
  TGL_BIT(PORTD,2); //toggle pin2 state   Â
 }
}
However I'm not really satisfied with the solution as in the MASTER code is need to use a "delaymicroseconds" in the "transferAndWait" routine to allow SLAVE to process and respond.
Is there anyway a non blocking code (ie not using delaymicroseconds) or somehow using a while loop to wait for SLAVE to respond instead.
Also there is a while loop already implemented in SPI.transfer to wait for a reply. so why do we need to add an addtional delay to get the SLAVE's response!!! 