RIOTOUS handles 95% of the work needed to get an IoT product working with the ESP8266 module. But since every device is unique, a few RIOTOUS functions have to be defined by the user. The following functions need to be defined by the user which are found in RIOTOUS_IO.c unless you download a specific flavour of RIOTOUS that matches your device (such as RIOTOUS PIC16F1516) in which case, RIOTOUS_IO.c has already been defined and you can dive straight into programming an IoT device!

  • void interrupt isr(void)
  • void riotous_configUART(void)
  • void riotous_sendByteUART(unsigned char data)
  • void riotous_turnInterruptsOff(void)
  • void riotous_turnInterruptsOn(void)
  • void riotous_delay(void)

 

void interrupt isr(void)

RIOTOUS is as interrupt driven as it can possibly be to ensure that there are no infinite loops and/or stalls. When a byte is received over UART, the interrupt service routine must send RIOTOUS framework the received byte by passing the byte to the function riotous_receiveByte(unsigned char byte). For example, the PIC16 would use riotous_receiveByte(RCREG). The interrupt service routine must also handle overflows and framing errors should they occur (PIC devices have a horrible habit of locking up the UART when one of these errors occur).

void riotous_configUART(void)

This function configures the UART module to do the following:

  • Clear the UART buffers
  • Configure the baud rate to 9600
  • Use 8 bits
  • Use 1 stop bit
  • Use no parity bits
  • Use asynchronous transmission
  • Configure the I/O pins for UART transmission / reception
  • Fire an interrupt upon receiving a UART byte

void riotous_delay(void)

This delay is imperative for proper ESP8266 communication and should delay for 100ms. This must not disable interrupts and must never be allowed to stall (i.e. use a simple while loop with a decrementing counter if possible).

void riotous_sendByteUART(unsigned char data)

This function needs to send a byte to the UART module for transmission, start the transmission, and wait until the byte has been sent.

void riotous_turnInterruptsOff(void)

This function needs to disable any interrupts from firing (i.e. disable global interrupts). This is crucial for RIOTOUS to function properly as C does not do well with atomic instructions. Turning interrupts off for short periods of time guarantees the framework that data buffers and variables are not being altered by external code.

void riotous_turnInterruptsOn(void)

This function needs to enabled interrupts globally. When RIOTOUS access vital variables, interrupts are disabled and once these sensitive operations have been completed, interrupts are re-enabled with this function.

 

PIC16 Example

Step 2 is a lot to read and understand so if you are either using a generic PIC16 device (such as the PIC16F1516) or the RIOTOUS devboard then the code below should suffice!


// -----------------------------------------------------------------------------
// Description : RIOTOUS User IO : You need to fill these functions in!
// Author : Robin Mitchell
// Company : MitchElectronics
// -----------------------------------------------------------------------------

#include <xc.h>
#include "RIOTOUS.h"

// -----------------------------------------------------------------------------
// This is your main interrupt function. Send the UART byte to
// riotous_receiveByte function. Also ensure to check for overflows and frame
// errors
// -----------------------------------------------------------------------------
void interrupt isr(void)
{
if (PIR1bits.RCIF)
{
if(RCSTAbits.FERR)
{
RCSTAbits.FERR = 0;
unsigned char garbage = RCREG;
garbage = RCREG;
garbage = RCREG;
garbage = RCREG;
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}

if(RCSTAbits.OERR)
{
RCSTAbits.OERR = 0;
unsigned char garbage = RCREG;
garbage = RCREG;
garbage = RCREG;
garbage = RCREG;
riotous_configUART();
RCSTAbits.CREN = 0;
RCSTAbits.CREN = 1;
}

riotous_receiveByte(RCREG);
}

INTCONbits.GIE = 1;
}

// -----------------------------------------------------------------------------
// This must configure the UART module to fire an interrupt on reception
// It must also change the baud rate to the ESP8266 rate (9600), use 8 bits,
// no parity, and one stop bit. It may be a good idea to configure the port pins
// here!
// -----------------------------------------------------------------------------
void riotous_configUART(void)
{
unsigned char garbage; // Used for clearing registers
garbage = RCREG;
garbage = RCREG;
garbage = RCREG;

TXSTAbits.BRGH = 0; // High Baud Rate
BAUDCONbits.BRG16 = 0; // 16 Bit SPBRG
SPBRGH = 0x00;
SPBRG = 25;

TXSTAbits.SYNC = 0; // Async communication
RCSTAbits.SPEN = 1; // Enable serial port
TXSTAbits.TXEN = 1; // Enable transmission
RCSTAbits.CREN = 1; // Enable reception
PIE1bits.RCIE = 1; // Enable reception interrupt
PIR1bits.RCIF = 0; // Enable reception interrupt

garbage = RCREG;
garbage = RCREG;
garbage = RCREG;
garbage = RCREG;

TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;
}

// -----------------------------------------------------------------------------
// This must send a byte to the UART transmitter register
// -----------------------------------------------------------------------------
void riotous_sendByteUART(unsigned char data)
{
TXREG = data; // Transfer byte to UART send register
while(!TXSTAbits.TRMT); // Wait until byte sent
}

// -----------------------------------------------------------------------------
// This turns interrupts off during crucial variable accesses. Probably the
// most important function here!
// -----------------------------------------------------------------------------
void riotous_turnInterruptsOff(void)
{
INTCONbits.GIE = 0;
}

// -----------------------------------------------------------------------------
// This turns interrupts on once key variables have been altered
// -----------------------------------------------------------------------------
void riotous_turnInterruptsOn(void)
{
INTCONbits.GIE = 1;
}

// -----------------------------------------------------------------------------
// This should delay for 100ms
// -----------------------------------------------------------------------------
void riotous_delay(void)
{
for(unsigned int i = 0; i &lt; 1000; i++)
{
}
}