Si4432

Coming soon!

New version on STM32 board. Maybe later on Arduino. So far, it works as communication device between two terminals. Also possible to use as remote for various toys. No code yet, need to clean it up a bit.

Still working on it, but here are first codes for STM32, later will be added codes for Arduino.

Semiduplex communication with Si4432 for STM32

Test code: working one for TX and RX. Sorry for Croatian comments…

// Moja verzija je B1, EZRadioPRO, == 00110
// Si4430/31/32 Rev B1: 00110.
// Si100x Rev C, Si101x Rev A, Si102x/3x Rev A: 00110.
// Si100x Rev E, Si101x Rev B: Si102x/3x Rev B: 00111.
#include <SPI.h>

//One out of these definitions has to be uncommented which tells to the compiler what kind
//of Testcard is plugged into the Software Development board
//#define SEPARATE_RX_TX
//#define ANTENNA_DIVERSITY 
#define ONE_SMA_WITH_RF_SWITCH //we will use as breakout board has - antenna switch

//byte reg1, reg2;
uint8_t cmd;
byte NIRQ=2;
byte NSS=10; //PB2, or SS pin
byte SDN=3;
byte PB=4;
//uint8_t value;
byte ItStatus1,ItStatus2;
byte Length,c;
uint8_t payload[11];
uint8_t temp8;

void setup() 
{
//pinMode(A0,1);// LED1, 0=input, 1=output
//pinMode(A1,1);// LED2
//pinMode(A2,1);// LED3
//pinMode(A3,1);// LED4
DDRB |= B00101100; //PB2, PB3 and PB5 are outputs (SS,MOSI,SCK) 
DDRC |= B00001111; //PC0, PC1, PC2 and PC3 are outputs for LEDs
//pinMode(2,INPUT); //set below as DDRD |=B00001X10, where X we may replace with 0
//pinMode(NSS,1); //pin PB2
//pinMode(SDN,1); //pin PD3, already set by DDRD |=B0000X000, where X should be replaced with 1
//pinMode(4,INPUT_PULLUP);
PORTD |= (1<<4); //pullup resistor on PD4
PORTD |= (1<<0); //pullup resistor for UART RX, maybe not needed?!
DDRD |= B00001010; //all inputs except PD3, which is SDN on Si4432 chip, and PD1, which is UART TX
//digitalWrite(A0,0);digitalWrite(A1,0);digitalWrite(A2,0);digitalWrite(A3,0);//turn off LEDs
PORTC &= ~(1<<0);PORTC &= ~(1<<1);PORTC &= ~(1<<2); PORTC &= ~(1<<3); //turn off all LEDs
Serial.begin(115200);
SPI.begin();
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV2);  //was 16
SPI.setBitOrder(MSBFIRST); 

//Turn on the radio by pulling down the PWRDN pin, or "SDN" pin 
//digitalWrite(3,0);// SDN = 0, or zero on PD3  
PORTD &= ~(1<<3); //PD3 goes to zero
//Wait at least 15ms befory any initialization SPI commands are sent to the radio  
// (wait for the power on reset sequence)   
delay(17); //more than 15 mS, so I put rather 17 mS
//read interrupt status registers to clear the interrupt flags and release NIRQ pin  
ItStatus1 = SpiReadRegister(0x03);  //read the Interrupt Status1 register  
ItStatus2 = SpiReadRegister(0x04);  //read the Interrupt Status2 register  
      
//SW reset     
SpiWriteRegister(0x07, 0x80);   //write 0x80 to the Operating & Function Control1 register   
          
//wait for POR interrupt from the radio (while the nIRQ pin is high)  
//while (digitalRead(NIRQ) == 1);    
while(PIND&4); //ovaj PIND&4 je ekvivalent digitalRead(NIRQ)==1
//read interrupt status registers to clear the interrupt flags and release NIRQ pin  
ItStatus1 = SpiReadRegister(0x03);    //read the Interrupt Status1 register  
ItStatus2 = SpiReadRegister(0x04);    //read the Interrupt Status2 register  
      
//wait for chip ready interrupt from the radio (while the nIRQ pin is high)  
//while(digitalRead(NIRQ)==1);
while(PIND&4); //isto while(digitalRead(NIRQ)==1   
//read interrupt status registers to clear the interrupt flags and release NIRQ pin  
ItStatus1 = SpiReadRegister(0x03);   //read the Interrupt Status1 register  
ItStatus2 = SpiReadRegister(0x04);   //read the Interrupt Status2 register  
                              
     /*set the physical parameters*/  
//set the center frequency to 915 MHz  
SpiWriteRegister(0x75, 0x40|0x13);  //write 0x75 to the Frequency Band Select register        0x75=117 B01110101, 0x65=101 B01100101      
SpiWriteRegister(0x76, 0x4e);  //write 0xBB to the Nominal Carrier Frequency1 register   0xBB=187, B10111011
SpiWriteRegister(0x77, 0x00);  //write 0x80 to the Nominal Carrier Frequency0 register   0x80=128, B10000000 0xBB80 gives: 48000
//f=(5+24+(48000/64000)*10000*(1+1)=... first parameter no more than 23 DEC or 0x17 , else math may be wrong

  //SpiWriteRegister(0x75,0x13); //was 0x75 for 915 MHz
  //SpiWriteRegister(0x76,0x62); //was 0xBB for 915 MHz
  //SpiWriteRegister(0x77,0x00); //was,0x80 for 915 MHz
          
 //set the desired TX data rate (9.6kbps)  
SpiWriteRegister(0x6E, 0x4E);  //write 0x4E to the TXDataRate 1 register  
SpiWriteRegister(0x6F, 0xA5);  //write 0xA5 to the TXDataRate 0 register  
SpiWriteRegister(0x70, 0x2C);  //write 0x2C to the Modulation Mode Control 1 register  
      
//set the Tx deviation register (+-45kHz)  
SpiWriteRegister(0x72, 0x10);  //write 0x48 to the Frequency Deviation register 
//I made it 0x12 or 625 kHz * 18 = 11.25 khz for 9.6 kbps (0x12) 
      
      
    /*set the modem parameters according to the exel calculator(parameters: 9.6 kbps,
     * deviation: 45 kHz, channel filter BW: 102.2 kHz*/  
SpiWriteRegister(0x1C, 0x12);  //write 0x1E to the IF Filter Bandwidth register          
SpiWriteRegister(0x20, 0xD0);  //write 0xD0 to the Clock Recovery Oversampling Ratio register        
SpiWriteRegister(0x21, 0x00);  //write 0x00 to the Clock Recovery Offset 2 register          
SpiWriteRegister(0x22, 0x9D);  //write 0x9D to the Clock Recovery Offset 1 register          
SpiWriteRegister(0x23, 0x49);  //write 0x49 to the Clock Recovery Offset 0 register          
SpiWriteRegister(0x24, 0x00);  //write 0x00 to the Clock Recovery Timing Loop Gain 1 register        
SpiWriteRegister(0x25, 0x24);  //write 0x24 to the Clock Recovery Timing Loop Gain 0 register        
SpiWriteRegister(0x1D, 0x40);  //write 0x40 to the AFC Loop Gearshift Override register          
SpiWriteRegister(0x1E, 0x0A);  //write 0x0A to the AFC Timing Control register       
SpiWriteRegister(0x2A, 0x20);   //write 0x20 to the AFC Limiter register          
                              
     /*set the packet structure and the modulation type*/  
//set the preamble length to 5bytes   
SpiWriteRegister(0x34, 0x0A);   //write 0x0A to the Preamble Length register  
//set preamble detection threshold to 20bits  
SpiWriteRegister(0x35, 0x2A);   //write 0x2A to the Preamble Detection Control  register  
      
//Disable header bytes; set variable packet length (the length of the payload is defined by the  
//received packet length field of the packet); set the synch word to two bytes long  
SpiWriteRegister(0x33, 0x02);  //write 0x02 to the Header Control2 register      
          
//Set the sync word pattern to 0x2DD4  
SpiWriteRegister(0x36, 0x2D);  //write 0x2D to the Sync Word 3 register  
SpiWriteRegister(0x37, 0xD4);  //write 0xD4 to the Sync Word 2 register  
      
//enable the TX & RX packet handler and CRC-16 (IBM) check  
SpiWriteRegister(0x30, 0x8D);   //write 0x8D to the Data Access Control register  
//Disable the receive header filters  
SpiWriteRegister(0x32, 0x00 );   //write 0x00 to the Header Control1 register              
//enable FIFO mode and GFSK modulation  
SpiWriteRegister(0x71, 0x63);   //write 0x63 to the Modulation Mode Control 2 register  
      
    /*set the GPIO's according to the RF switch */  
SpiWriteRegister(0x0b, 0x12); //write 0x12 to the GPIO1 Configuration(set the TX state)  
SpiWriteRegister(0x0c, 0x15); //write 0x15 to the GPIO2 Configuration(set the RX state)   
      
       /*set the non-default Si443x registers*/  
//set  cap. bank  
SpiWriteRegister(0x09, 0xAC); //write 0xD7 to the Crystal Oscillator Load Capacitance register  
// Set AGC Override1 Register  
SpiWriteRegister(0x69, 0x60); //write 0x60 to the AGC Override1 register    
      
   /*enable receiver chain*/  
SpiWriteRegister(0x07, 0x05); //write 0x05 to the Operating Function Control 1 register  
//Enable two interrupts:   
// a) one which shows that a valid packet received: 'ipkval'  
// b) second shows if the packet received with incorrect CRC: 'icrcerror'   
SpiWriteRegister(0x05, 0x03);  //write 0x03 to the Interrupt Enable 1 register  
SpiWriteRegister(0x06, 0x00);  //write 0x00 to the Interrupt Enable 2 register  
//read interrupt status registers to release all pending interrupts  
ItStatus1 = SpiReadRegister(0x03);  //read the Interrupt Status1 register  
ItStatus2 = SpiReadRegister(0x04);  //read the Interrupt Status2 register  

//moje:
//Power settings !!!
SpiWriteRegister(0x6D,0x00);// 0x00 is minimum power, 0x07 is max power! was: (0x6D,0x08|0x00)

}

void loop() 
{
 
   //Poll the port pins of the MCU to figure out whether the push button is pressed or not  
   //if(digitalRead(PB) == 0) 
   if((PIND&16) == 0) //check PD4 to become zero
     {     
       //Wait for releasing the push button  
       //while(digitalRead(PB) == 0);  
       while((PIND&16)==0);  //waiting into the while loop until PD4 is again 1
       //disable the receiver chain (but keep the XTAL running to have shorter TX on time!)  
       SpiWriteRegister(0x07, 0x01); //write 0x01 to the Operating Function Control 1 register             
      
       //turn on the LED to show the packet transmission  
       //digitalWrite(A0,1); //TX_LED = 1                                                                       
       PORTC |= (1<<0); //PC0 goes to 1, zero shifting left of value 1
       /*SET THE CONTENT OF THE PACKET*/  
       //set the length of the payload to 8bytes     
       SpiWriteRegister(0x3E, 8); //write 8 to the Transmit Packet Length register          
       //fill the payload into the transmit FIFO  
       SpiWriteRegister(0x7F, 0x42); //write 0x42 ('B') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x55); //write 0x55 ('U') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x54); //write 0x54 ('T') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x54); //write 0x54 ('T') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x4F); //write 0x4F ('O') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x4E); //write 0x4E ('N') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x31); //write 0x31 ('1') to the FIFO Access register    
       SpiWriteRegister(0x7F, 0x0D); //write 0x0D (CR) to the FIFO Access register     
      
       //Disable all other interrupts and enable the packet sent interrupt only.  
       //This will be used for indicating the successfull packet transmission for the MCU  
       SpiWriteRegister(0x05, 0x04); //write 0x04 to the Interrupt Enable 1 register   
       SpiWriteRegister(0x06, 0x00); //write 0x03 to the Interrupt Enable 2 register   
       //Read interrupt status regsiters. It clear all pending interrupts and the nIRQ pin goes back to high.  
       ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
       ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
      
       /*enable transmitter*/  
       //The radio forms the packet and send it automatically.  
       SpiWriteRegister(0x07, 0x09);  //write 0x09 to the Operating Function Control 1 register  
      
       /*wait for the packet sent interrupt*/  
       //The MCU just needs to wait for the 'ipksent' interrupt.  
       //while(digitalRead(NIRQ) == 1);  
       while(PIND&4); //while NIRQ==1
       //read interrupt status registers to release the interrupt flags  
       ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
       ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
      
       //wait a bit for showing the LED a bit longer  
       delay(10);  //was delay(10) - DO NOT increase on single end!
       //turn off the LED  
       //digitalWrite(A0,0);  //TX_LED = 0
       PORTC &= ~(1<<PC0); //not! zero shifted 0 from right to left, so PC0=0
                         
       //after packet transmission set the interrupt enable bits according receiving mode  
       //Enable two interrupts:   
       // a) one which shows that a valid packet received: 'ipkval'  
       // b) second shows if the packet received with incorrect CRC: 'icrcerror'   
       SpiWriteRegister(0x05, 0x03); //write 0x03 to the Interrupt Enable 1 register  
       SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register  
       //read interrupt status registers to release all pending interrupts  
       ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
       ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
      
       /*enable receiver chain again*/  
       SpiWriteRegister(0x07, 0x05);  //write 0x05 to the Operating Function Control 1 register                 
     }  
      
              
  //wait for the interrupt event  
  //If it occurs, then it means a packet received or CRC error happened  
  //if(digitalRead(NIRQ) == 0 )
  if ((PIND&4)==0)  //NIRQ pin is PD2
    {  
      //disable the receiver chain   
      SpiWriteRegister(0x07, 0x01); //write 0x01 to the Operating Function Control 1 register  
      //read interrupt status registers   
      ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
      ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
      
      /*CRC Error interrupt occured*/  
      if( (ItStatus1 & 0x01) == 0x01 )  
        {  
          //reset the RX FIFO  
          SpiWriteRegister(0x08, 0x02); //write 0x02 to the Operating Function Control 2 register  
          SpiWriteRegister(0x08, 0x00); //write 0x00 to the Operating Function Control 2 register  
          //blink all LEDs to show the error  
          //digitalWrite(A0,1); //TX_LED = 1 
          PORTC |= (1<<0);
          //digitalWrite(A1,1); //RX_LED = 1 
          PORTC |= (1<<1);
          delay(10); //was delay(10) - DO NOT increase on single end!
          //digitalWrite(A0,0); //TX_LED = 0
          PORTC &= ~(1<<0);  
          //digitalWrite(A1,0); //RX_LED = 0 
          PORTC &= ~(1<<1); 
        }  
      
      /*packet received interrupt occured*/  
      if( (ItStatus1 & 0x02) == 0x02 )  
        {  
          //Read the length of the received payload  
          Length = SpiReadRegister(0x4B); //read the Received Packet Length register  
          //check whether the received payload is not longer than the allocated buffer in the MCU  
          if(Length < 11)  
            {  
               //Get the reeived payload from the RX FIFO  
               for(temp8=0;temp8 < Length;temp8++)  
               {  
                  payload[temp8] = SpiReadRegister(0x7F); //read the FIFO Access register  
                  Serial.print((char)payload[temp8]);
               }  
                 Serial.println(""); 
            //check whether the acknowledgement packet received  
            if( Length == 4 )   
              {  
                if( memcmp(&payload[0], "ACK", 3) == 0 )  
                  {  
                    //blink LED2 to show that ACK received  
                    //digitalWrite(A1,1); //RX_LED = 1
                    PORTC |=(1<<1);
                    delay(10); //was delay(10)- DO NOT increase on single end!
                    //digitalWrite(A1,0); //RX_LED = 0
                    PORTC &= ~(1<<1);
                  }  
             }  
      
             //check whether an expected packet received, this should be acknowledged  
             if( Length == 8 )   
               {  
                 if( memcmp(&payload[0], "BUTTON1", 7) == 0 )  
                   {  
                     //blink LED2 to show that the packet received  
                     //digitalWrite(A1,1); //RX_LED = 1
                     PORTC |= (1<<1);
                     delay(10); //was delay(10) - DO NOT increase on single end!
                     //digitalWrite(A1,0); //RX_LED = 0  
                     PORTC &= ~(1<<1);
      
                     /*send back an acknowledgement*/  
                     //turn on LED1 to show packet transmission  
                     //digitalWrite(A0,1); //TX_LED = 1
                     PORTC |= (1<<0);
                     /*set packet content*/  
                     //set the length of the payload to 4bytes     
                     SpiWriteRegister(0x3E, 4); //write 4 to the Transmit Packet Length register          
                     //fill the payload into the transmit FIFO  
                     SpiWriteRegister(0x7F, 0x41); //write 0x41 ('A') to the FIFO Access register    
                     SpiWriteRegister(0x7F, 0x43); //write 0x43 ('C') to the FIFO Access register    
                     SpiWriteRegister(0x7F, 0x4B); //write 0x4B ('K') to the FIFO Access register    
                     SpiWriteRegister(0x7F, 0x0D); //write 0x0D (CR) to the FIFO Access register     
      
                     //Disable all other interrupts and enable the packet sent interrupt only.  
                     //This will be used for indicating the successfull packet transmission for the MCU  
                     SpiWriteRegister(0x05, 0x04); //write 0x04 to the Interrupt Enable 1 register   
                     SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register   
                     //Read interrupt status regsiters. It clear all pending interrupts and the nIRQ pin goes back to high.  
                     ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
                     ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
      
                     /*enable transmitter*/  
                     //The radio forms the packet and send it automatically.  
                     SpiWriteRegister(0x07, 0x09); //write 0x09 to the Operating Function Control 1 register  
      
                     /*wait for the packet sent interrupt*/  
                     //The MCU just needs to wait for the 'ipksent' interrupt.  
                     //while(digitalRead(NIRQ) == 1);  
                     while(PIND&4);
                     //read interrupt status registers to release the interrupt flags  
                     ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
                     ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
      
                     //wait a bit for showing the LED a bit longer  
                     delay(10); //was delay(10) - DO NOT increase on single end!
                     //turn off the LED  
                     //digitalWrite(A0,0); //TX_LED = 0
                     PORTC &= ~(1<<0);
      
                     //after packet transmission set the interrupt enable bits according receiving mode  
                     //Enable two interrupts:   
                     // a) one which shows that a valid packet received: 'ipkval'  
                     // b) second shows if the packet received with incorrect CRC: 'icrcerror'   
                     SpiWriteRegister(0x05, 0x03); //write 0x03 to the Interrupt Enable 1 register  
                     SpiWriteRegister(0x06, 0x00); //write 0x00 to the Interrupt Enable 2 register  
                     //read interrupt status registers to release all pending interrupts  
                     ItStatus1 = SpiReadRegister(0x03); //read the Interrupt Status1 register  
                     ItStatus2 = SpiReadRegister(0x04); //read the Interrupt Status2 register  
                   }  
               }  
           }  
       }  
     //reset the RX FIFO  
     SpiWriteRegister(0x08, 0x02); //write 0x02 to the Operating Function Control 2 register  
     SpiWriteRegister(0x08, 0x00); //write 0x00 to the Operating Function Control 2 register  
     //enable the receiver chain again  
     SpiWriteRegister(0x07, 0x05);  //write 0x05 to the Operating Function Control 1 register  
  }     
          
}

void SpiWriteRegister(uint8_t reg,uint8_t cmd)
  {
    //digitalWrite(NSS,0); //Select the radio by pulling the nSEL pin to low (NSS=10), PB2
    PORTB &= ~(1<<2); //pin PB2 is 0
    SPI.transfer(0x80|reg)  ;// 0x80 is first nRW bit high (1), IMPORTANT!
    SPI.transfer(cmd); ;// command is full byte
    //digitalWrite(NSS,1); //Deselect the radio by pulling high the nSEL pin
    PORTB |= (1<<2); //pin PB2 is 1
   }

 byte SpiReadRegister(uint8_t reg)
{
    //digitalWrite(NSS,0); //Select the radio by pulling the nSEL pin to low 
    PORTB &= ~(1<<2); //PB2 is 0
    SPI.transfer(reg);
    c=SPI.transfer(0)  ;// "value" not really needed for purpose of reset flags, but...was Length
    //digitalWrite(NSS,1); //Deselect the radio by pulling high the nSEL pin
    PORTB |= (1<<2); //PB2 is 1
    
    return c;
}

Science and more

%d bloggers like this: