LightwaveRF library port for spark

Hi
Can anybody help me to port this for the spark? It is for lightwaverf home automation but will not compile for the due. I have no idea how to even start doing this hence this post. For now I am using a custom yabbas to receive and transmit lightwaverf and interfacing to a Sainsmart due for network connectivity, it works but is not ideal, the yabbas cannot keep up with the signals! This is why I ordered a spark, I was hoping it would cut out loads of peripherals but it is no real use if I can’t port this library.

    // LwRx.cpp
//
// LightwaveRF 434MHz receiver interface for Arduino
// 
// Author: Bob Tidey (robert@tideys.net)

#include <LwRx.h>
//define EEPROMaddr to location to store pair data or -1 to skip EEPROM
//First byte is pair count followed by 8 byte pair addresses (device,dummy,5*addr,room)
#define EEPROMaddr -1

static const byte rx_nibble[] = {0xF6,0xEE,0xED,0xEB,0xDE,0xDD,0xDB,0xBE,0xBD,0xBB,0xB7,0x7E,0x7D,0x7B,0x77,0x6F};
static const byte rx_cmd_off     = 0xF6; // raw 0
static const byte rx_cmd_on      = 0xEE; // raw 1
static const byte rx_cmd_mood    = 0xED; // raw 2
static const byte rx_par0_alloff = 0x7D; // param 192-255 all off (12 in msb)
static const byte rx_dev_15      = 0x6F; // device 15

static int rx_pin = 2;
static const byte rx_msglen = 10; // expected length of rx message

//Receive mode constants and variables
static byte rx_msg[rx_msglen]; // raw message received
static byte rx_buf[rx_msglen]; // message buffer during reception

static unsigned long rx_prev; // time of previous interrupt in microseconds

static boolean rx_msgcomplete = false; //set high when message available
static boolean rx_translate = true; // Set false to get raw data

static byte rx_state = 0;
static const byte rx_state_idle = 0;
static const byte rx_state_msgstartfound = 1;
static const byte rx_state_bytestartfound = 2;
static const byte rx_state_getbyte = 3;

static byte rx_num_bits = 0; // number of bits in the current byte
static byte rx_num_bytes = 0; // number of bytes received 

//Pairing data
static byte rx_paircount = 0;
static byte rx_pairs[rx_maxpairs][8];
static byte rx_pairtimeout = 0; // 100msec units
//set false to responds to all messages if no pairs set up
static boolean rx_pairEnforce = false;
//set false to use Address, Room and Device in pairs, true just the Address part
static boolean rx_pairBaseOnly = false;

// Repeat filters
static byte rx_repeats = 2; //msg must be repeated at least this number of times
static byte rx_repeatcount = 0;
static byte rx_timeout = 20; //reset repeat window after this in 100mSecs
static unsigned long rx_prevpkttime = 0; //last packet time in milliseconds
static unsigned long rx_pairstarttime = 0; //last msg time in milliseconds

// Gather stats for pulse widths (ave is x 16)
static const unsigned int lwrx_statsdflt[rx_stat_count] = {5000,0,5000,20000,0,2500,4000,0,500};
static unsigned int lwrx_stats[rx_stat_count];
static boolean lwrx_stats_enable = true;

/**
  Pin change interrupt routine that identifies 1 and 0 LightwaveRF bits
  and constructs a message when a valid packet of data is received.
**/
void rx_process_bits() { 
   byte event = digitalRead(rx_pin); // start setting event to the current value
   unsigned long curr = micros(); // the current time in microseconds

   unsigned int dur = (curr-rx_prev);
   rx_prev = curr;
   //set event based on input and duration of previous pulse
   if(dur < 120) { //120 very short
   } else if(dur < 500) { // normal short pulse
      event +=2;
   } else if(dur < 2000) { // normal long pulse
      event +=4;
   } else if(dur > 5000){ // gap between messages
      event +=6;
   } else { //2000 > 5000
      event = 8; //illegal gap
   } 
   //state machine transitions 
   switch(rx_state) {
      case rx_state_idle:
         switch(event) {
           case 7: //1 after a message gap
             rx_state = rx_state_msgstartfound;
             break;
         }
         break;
      case rx_state_msgstartfound:
         switch(event) {
            case 2: //0 160->500
             //nothing to do wait for next positive edge
               break;
            case 3: //1 160->500
               rx_num_bytes = 0;
               rx_state = rx_state_bytestartfound;
               break;
            default:
               //not good start again
               rx_state = rx_state_idle;
               break;
         }
         break;
      case rx_state_bytestartfound:
         switch(event) {
            case 2: //0 160->500
               //nothing to do wait for next positive edge
               break;
            case 3: //1 160->500
               rx_state = rx_state_getbyte;
               rx_num_bits = 0;
               break;
            case 5: //0 500->1500
               rx_state = rx_state_getbyte;
               // Starts with 0 so put this into byte
               rx_num_bits = 1;
               rx_buf[rx_num_bytes] = 0;
               break;
            default: 
               //not good start again
               rx_state = rx_state_idle;
               break;
         }
         break;
      case rx_state_getbyte:
         switch(event) {
            case 2: //0 160->500
               //nothing to do wait for next positive edge but do stats
               if(lwrx_stats_enable) {
                  lwrx_stats[rx_stat_high_max] = max(lwrx_stats[rx_stat_high_max], dur);
                  lwrx_stats[rx_stat_high_min] = min(lwrx_stats[rx_stat_high_min], dur);
                  lwrx_stats[rx_stat_high_ave] = lwrx_stats[rx_stat_high_ave] - (lwrx_stats[rx_stat_high_ave] >> 4) + dur;
               }
               break;
            case 3: //1 160->500
               // a single 1
               rx_buf[rx_num_bytes] = rx_buf[rx_num_bytes] << 1 | 1;
               rx_num_bits++;
               if(lwrx_stats_enable) {
                  lwrx_stats[rx_stat_low1_max] = max(lwrx_stats[rx_stat_low1_max], dur);
                  lwrx_stats[rx_stat_low1_min] = min(lwrx_stats[rx_stat_low1_min], dur);
                  lwrx_stats[rx_stat_low1_ave] = lwrx_stats[rx_stat_low1_ave] - (lwrx_stats[rx_stat_low1_ave] >> 4) + dur;
               }
               break;
            case 5: //1 500->1500
               // a 1 followed by a 0
               rx_buf[rx_num_bytes] = rx_buf[rx_num_bytes] << 2 | 2;
               rx_num_bits++;
               rx_num_bits++;
               if(lwrx_stats_enable) {
                  lwrx_stats[rx_stat_low0_max] = max(lwrx_stats[rx_stat_low0_max], dur);
                  lwrx_stats[rx_stat_low0_min] = min(lwrx_stats[rx_stat_low0_min], dur);
                  lwrx_stats[rx_stat_low0_ave] = lwrx_stats[rx_stat_low0_ave] - (lwrx_stats[rx_stat_low0_ave] >> 4) + dur;
               }
               break;
            default:
               //not good start again
               rx_state = rx_state_idle;
               break;
         }
         if(rx_num_bits >= 8) {
            rx_num_bytes++;
            rx_num_bits = 0;
            if(rx_num_bytes >= rx_msglen) {
               unsigned long currMillis = millis();
               if(rx_repeats > 0) {
                  if((currMillis - rx_prevpkttime) / 100 > rx_timeout) { 
                     rx_repeatcount = 1;
                  } else {
                     //Test message same as last one
                     int i = rx_msglen;
                     do {
                        i--;
                     }
                     while((i >= 0) && (rx_msg[i] == rx_buf[i]));
                     if(i < 0) {
                        rx_repeatcount++;
                     } else {
                        rx_repeatcount = 1;
                     }
                  }
               } else {
                  rx_repeatcount = 0;
               }
               rx_prevpkttime = currMillis;
               //If last message hasn't been read it gets overwritten
               memcpy(rx_msg, rx_buf, rx_msglen); 
               if(rx_repeats == 0 || rx_repeatcount == rx_repeats) {
                  if(rx_pairtimeout != 0) {
                     if((currMillis - rx_pairstarttime) / 100 <= rx_pairtimeout) {
                        if(rx_msg[3] == rx_cmd_on) {
                           rx_addpairfrommsg();
                        } else if(rx_msg[3] == rx_cmd_off) {
                           rx_removePair(&rx_msg[2]);
                        }
                     }
                  }
                  if(rx_reportMessage()) {
                     rx_msgcomplete = true;
                  }
                  rx_pairtimeout = 0;
               }
               // And cycle round for next one
               rx_state = rx_state_idle;
            } else {
              rx_state = rx_state_bytestartfound;
            }
         }
         break;
   }
}

/**
  Test if a message has arrived
**/
boolean lwrx_message() {
   return (rx_msgcomplete);
}

/**
  Set translate mode
**/
void lwrx_settranslate(boolean rxtranslate) {
   rx_translate = rxtranslate;
}

/**
  Transfer a message to user buffer
**/
boolean lwrx_getmessage(byte *buf, byte len) {
   boolean ret = true;
   int j=0,k=0;
   if(rx_msgcomplete && len <= rx_msglen) {
      for(byte i=0; ret && i < rx_msglen; i++) {
         if(rx_translate || (len != rx_msglen)) {
            j = rx_findNibble(rx_msg[i]);
            if(j<0) ret = false;
         } else {
            j = rx_msg[i];
         }
         switch(len) {
            case 4:
               if(i==9) buf[2]=j;
               if(i==2) buf[3]=j;
            case 2:
               if(i==3) buf[0]=j;
               if(i==0) buf[1]=j<<4;
               if(i==1) buf[1]+=j;
               break;
            case 10:
               buf[i]=j;
               break;
         }
      }
      rx_msgcomplete= false; 
   } else {
      ret = false;
   }
   return ret;
}

/**
  Return time in milliseconds since last packet received
**/
unsigned long lwrx_packetinterval() {
   return millis() - rx_prevpkttime;
}

/**
  Set up repeat filtering of received messages
**/
void lwrx_setfilter(byte repeats, byte timeout) {
   rx_repeats = repeats;
   rx_timeout = timeout;
}

/**
  Add a pair to filter received messages
  pairdata is device,dummy,5*addr,room
  pairdata is held in translated form to make comparisons quicker
**/
byte lwrx_addpair(byte* pairdata) {
   if(rx_paircount < rx_maxpairs) {
      for(byte i=0; i<8; i++) {
         rx_pairs[rx_paircount][i] = rx_nibble[pairdata[i]];
      }
      rx_paircommit();
   }
   return rx_paircount;
}

/**
  Make a pair from next message successfully received
**/
extern void lwrx_makepair(byte timeout) {
   rx_pairtimeout = timeout;
   rx_pairstarttime = millis();
}

/**
  Get pair data (translated back to nibble form
**/
extern byte lwrx_getpair(byte* pairdata, byte pairnumber) {
   if(pairnumber < rx_paircount) {
      int j;
      for(byte i=0; i<8; i++) {
         j = rx_findNibble(rx_pairs[pairnumber][i]);
         if(j>=0) pairdata[i] = j;
      }
   }
   return rx_paircount;
}

/**
  Clear all pairing
**/
extern void lwrx_clearpairing() {
   rx_paircount = 0;
   if(EEPROMaddr >= 0) {
      EEPROM.write(EEPROMaddr, 0);
   }
}

/**
  Return stats on high and low pulses
**/
boolean lwrx_getstats(unsigned int *stats) {
   if(lwrx_stats_enable) {
      memcpy(stats, lwrx_stats, 2 * rx_stat_count);
      return true;
   } else {
      return false;
   }
}

/**
  Set stats mode
**/
void lwrx_setstatsenable(boolean rx_stats_enable) {
   lwrx_stats_enable = rx_stats_enable;
   if(!lwrx_stats_enable) {
      //clear down stats when disabling
      memcpy(lwrx_stats, lwrx_statsdflt, sizeof(lwrx_statsdflt));
   }
}
/**
  Set pairs behaviour
**/
void lwrx_setPairMode(boolean pairEnforce, boolean pairBaseOnly) {
   rx_pairEnforce = pairEnforce;
   rx_pairBaseOnly = pairBaseOnly;
}


/**
  Set things up to receive LightWaveRF 434Mhz messages
  pin must be 2 or 3 to trigger interrupts
**/
void lwrx_setup(int pin) {
   restoreEEPROMPairing();
   rx_pin = (pin == 3) ? 3 : 2;
   pinMode(rx_pin,INPUT);
   attachInterrupt(rx_pin - 2, rx_process_bits, CHANGE);
   memcpy(lwrx_stats, lwrx_statsdflt, sizeof(lwrx_statsdflt));
}

/**
  Check a message to see if it should be reported under pairing / mood / all off rules
  returns -1 if none found
**/
boolean rx_reportMessage() {
   if(rx_pairEnforce && rx_paircount == 0) {
      return false;
   } else {
      boolean allDevices;
      // True if mood to device 15 or Off cmd with Allof paramater
      allDevices = ((rx_msg[3] == rx_cmd_mood && rx_msg[2] == rx_dev_15) || 
                    (rx_msg[3] == rx_cmd_off && rx_msg[0] == rx_par0_alloff));
      return (rx_checkPairs(&rx_msg[2], allDevices) != -1);
   }
}
/**
  Find nibble from byte
  returns -1 if none found
**/
int rx_findNibble(byte data) {
   int i = 15;
   do {
      if(rx_nibble[i] == data) break;
      i--;
   } while (i >= 0);
   return i;
}

/**
  add pair from message buffer
**/
void rx_addpairfrommsg() {
   if(rx_paircount < rx_maxpairs) {
      memcpy(rx_pairs[rx_paircount], &rx_msg[2], 8);
      rx_paircommit();
   }
}

/**
  check and commit pair
**/
void rx_paircommit() {
   if(rx_paircount == 0 || rx_checkPairs(rx_pairs[rx_paircount], false) < 0) {
      if(EEPROMaddr >= 0) {
         for(byte i=0; i<8; i++) {
            EEPROM.write(EEPROMaddr + 1 + 8 * rx_paircount + i, rx_pairs[rx_paircount][i]);
         }
      }
      rx_paircount++;
      if(EEPROMaddr >= 0) {
         EEPROM.write(EEPROMaddr, rx_paircount);
      }
   }
}

/**
  Check to see if message matches one of the pairs
    if mode is pairBase only then ignore device and room
    if allDevices is true then ignore the device number
  Returns matching pair number, -1 if not found, -2 if no pairs defined
**/
int rx_checkPairs(byte *buf, boolean allDevices ) {
   if(rx_paircount ==0) {
      return -2;
   } else {
      int pair= rx_paircount;
      int j = -1;
      int jstart,jend;
      if(rx_pairBaseOnly) {
         // skip room(8) and dev/cmd (0,1)
         jstart = 7;
         jend = 2;
      } else {
         //include room in comparison
         jstart = 8;
         //skip device comparison if allDevices true
         jend = (allDevices) ? 2 : 0;
      }
      while (pair>0 && j<0) {
         pair--;
         j = jstart;
         while(j>jend){
            j--;
            if(j != 1) {
               if(rx_pairs[pair][j] != buf[j]) {
                  j = -1;
               }
            }
         }
      }
      return (j >= 0) ? pair : -1;
   }
}

/**
  Remove an existing pair matching the buffer
**/
void rx_removePair(byte *buf) {
   int pair = rx_checkPairs(buf, false);
   if(pair >= 0) {
      while (pair < rx_paircount - 1) {
         for(byte j=0; j<8;j++) {
            rx_pairs[pair][j] = rx_pairs[pair+1][j];
            if(EEPROMaddr >= 0) {
               EEPROM.write(EEPROMaddr + 1 + 8 * pair + j, rx_pairs[pair][j]);
            }
         }
         pair++;
      }
      rx_paircount--;
      if(EEPROMaddr >= 0) {
         EEPROM.write(EEPROMaddr, rx_paircount);
      }
   }
}

/**
   Retrieve and set up pairing data from EEPROM if used
**/
void restoreEEPROMPairing() {
   if(EEPROMaddr >= 0) {
      rx_paircount = EEPROM.read(EEPROMaddr);
      if(rx_paircount > rx_maxpairs) {
         rx_paircount = 0;
         EEPROM.write(EEPROMaddr, 0);
      } else {
         for( byte i=0; i < rx_paircount; i++) {
            for(byte j=0; j<8; j++) {
               rx_pairs[i][j] = EEPROM.read(EEPROMaddr + 1 + 8 * i + j);
            }
         }
      }
   }
}

    // LwRx.h
//
// LightwaveRF 434MHz receiver for Arduino
// 
// Author: Bob Tidey (robert@tideys.net)

#include <Arduino.h>
#include <../EEPROM/EEPROM.h>
#define rx_stat_high_ave 0
#define rx_stat_high_max 1
#define rx_stat_high_min 2
#define rx_stat_low0_ave 3
#define rx_stat_low0_max 4
#define rx_stat_low0_min 5
#define rx_stat_low1_ave 6
#define rx_stat_low1_max 7
#define rx_stat_low1_min 8
#define rx_stat_count 9

//sets maximum number of pairings which can be held
#define rx_maxpairs 10

//Setup must be called once, set up pin used to receive data
extern void lwrx_setup(int pin);

//Set translate to determine whether translating from nibbles to bytes in message
//Translate off only applies to 10char message returns
extern void lwrx_settranslate(boolean translate);

// Check to see whether message available
extern boolean lwrx_message();

//Get a message, len controls format (2 cmd+param, 4 cmd+param+room+device),10 full message
extern boolean lwrx_getmessage(byte* buf, byte len);

//Setup repeat filter
extern void lwrx_setfilter(byte repeats, byte timeout);

//Add pair, if no pairing set then all messages are received, returns number of pairs
extern byte lwrx_addpair(byte* pairdata);

// Get pair data into buffer  for the pairnumber. Returns current paircount
// Use pairnumber 255 to just get current paircount
extern byte lwrx_getpair(byte* pairdata, byte pairnumber);

//Make a pair from next message received within timeout 100mSec
//This call returns immediately whilst message checking continues
extern void lwrx_makepair(byte timeout);

//Set pair mode controls
extern void lwrx_setPairMode(boolean pairEnforce, boolean pairBaseOnly);

//Returns time from last packet received in msec
// Can be used to determine if Rx may be still receiving repeats
extern unsigned long lwrx_packetinterval();

extern void lwrx_clearpairing();

//Return stats on pulse timings
extern boolean lwrx_getstats(unsigned int* stats);

//Enable collection of stats on pulse timings
extern void lwrx_setstatsenable(boolean rx_stats_enable);

//internal support functions
boolean rx_reportMessage();
int rx_findNibble(byte data);
void rx_addpairfrommsg();
void rx_paircommit();
void rx_removePair(byte *buf);
int rx_checkPairs(byte *buf, boolean allDevices);
void restoreEEPROMPairing();

    // LwTx.cpp
//
// LightwaveRF 434MHz tx interface for Arduino
// 
// Author: Bob Tidey (robert@tideys.net)

#include <LwTx.h>

//define EEPROMaddr to location to store message addr or -1 to skip EEPROM
#define EEPROMaddr 0

static byte tx_nibble[] = {0xF6,0xEE,0xED,0xEB,0xDE,0xDD,0xDB,0xBE,0xBD,0xBB,0xB7,0x7E,0x7D,0x7B,0x77,0x6F};

static int tx_pin = 3;
static const byte tx_msglen = 10; // the expected length of the message

//Transmit mode constants and variables

static byte tx_repeats = 12; // Number of repeats of message sent
static byte txon = 1;
static byte txoff = 0;
static boolean tx_msg_active = false; //set true to activate message sending
static boolean tx_translate = true; // Set false to send raw data

static byte tx_buf[tx_msglen]; // the message buffer during reception
static byte tx_repeat = 0; //counter for repeats
static byte tx_state = 0;
static byte tx_toggle_count = 3;
static unsigned int tx_gap_repeat = 0;

// These set the pulse durations in ticks
static byte tx_low_count = 7; // total number of ticks in a low (980 uSec)
static byte tx_high_count = 4; // total number of ticks in a high (560 uSec)
static byte tx_trail_count = 2; //tick count to set line low (280 uSec)
// Use with low repeat counts
static byte tx_gap_count = 72; // Inter-message gap count (10.8 msec)
//Gap multiplier byte is used to multiply gap if longer periods are needed for experimentation
//If gap is 255 (35msec) then this to give a max of 9 seconds
//Used with low repeat counts to find if device times out
static byte tx_gap_multiplier = 0; //Gap extension byte 

static const byte tx_state_idle = 0;
static const byte tx_state_msgstart = 1;
static const byte tx_state_bytestart = 2;
static const byte tx_state_sendbyte = 3;
static const byte tx_state_msgend = 4;
static const byte tx_state_gapstart = 5;
static const byte tx_state_gapend = 6;

static byte tx_bit_mask = 0; // bit mask in current byte
static byte tx_num_bytes = 0; // number of bytes sent 

/**
  Set translate mode
**/
void lwtx_settranslate(boolean txtranslate)
{
    tx_translate = txtranslate;
}

ISR(TIMER2_COMPA_vect){
   //Set low after toggle count interrupts
   tx_toggle_count--;
   if (tx_toggle_count == tx_trail_count) {
      digitalWrite(tx_pin, txoff);
   } else if (tx_toggle_count == 0) {
     tx_toggle_count = tx_high_count; //default high pulse duration
     switch (tx_state) {
       case tx_state_idle:
         if(tx_msg_active) {
           tx_repeat = 0;
           tx_state = tx_state_msgstart;
         }
         break;
       case tx_state_msgstart:
         digitalWrite(tx_pin, txon);
         tx_num_bytes = 0;
         tx_state = tx_state_bytestart;
         break;
       case tx_state_bytestart:
         digitalWrite(tx_pin, txon);
         tx_bit_mask = 0x80;
         tx_state = tx_state_sendbyte;
         break;
       case tx_state_sendbyte:
         if(tx_buf[tx_num_bytes] & tx_bit_mask) {
           digitalWrite(tx_pin, txon);
         } else {
           // toggle count for the 0 pulse
           tx_toggle_count = tx_low_count;
         }
         tx_bit_mask >>=1;
         if(tx_bit_mask == 0) {
           tx_num_bytes++;
           if(tx_num_bytes >= tx_msglen) {
             tx_state = tx_state_msgend;
           } else {
             tx_state = tx_state_bytestart;
           }
         }
         break;
       case tx_state_msgend:
         digitalWrite(tx_pin, txon);
         tx_state = tx_state_gapstart;
         tx_gap_repeat = tx_gap_multiplier;
         break;
       case tx_state_gapstart:
         tx_toggle_count = tx_gap_count;
         if (tx_gap_repeat == 0) {
            tx_state = tx_state_gapend;
         } else {
            tx_gap_repeat--;
         }
         break;
       case tx_state_gapend:
         tx_repeat++;
         if(tx_repeat >= tx_repeats) {
           //disable timer 2 interrupt
           TIMSK2 &= ~(1 << OCIE2A);
           tx_msg_active = false;
           tx_state = tx_state_idle;
         } else {
            tx_state = tx_state_msgstart;
         }
         break;
     }
   }
}

/**
  Check for send free
**/
boolean lwtx_free() {
  return !tx_msg_active;
}

/**
  Send a LightwaveRF message (10 nibbles in bytes)
**/
void lwtx_send(byte *msg) {
  if (tx_translate) {
    for (byte i=0; i < tx_msglen; i++) {
      tx_buf[i] = tx_nibble[msg[i] & 0xF];
    }
  } else {
    memcpy(tx_buf, msg, tx_msglen);
  }
  //enable timer 2 interrupts
  TIMSK2 |= (1 << OCIE2A);
  tx_msg_active = true;
}

/**
  Set 5 char address for future messages
**/
void lwtx_setaddr(byte *addr) {
   for (byte i=0; i < 5; i++) {
      tx_buf[i+4] = tx_nibble[addr[i] & 0xF];
      if(EEPROMaddr >= 0) {
         EEPROM.write(EEPROMaddr + i, tx_buf[i+4]);
      }
   }
}

/**
  Send a LightwaveRF message (10 nibbles in bytes)
**/
void lwtx_cmd(byte command, byte parameter, byte room, byte device) {
  //enable timer 2 interrupts
  tx_buf[0] = tx_nibble[parameter >> 4];
  tx_buf[1] = tx_nibble[parameter  & 0xF];
  tx_buf[2] = tx_nibble[device  & 0xF];
  tx_buf[3] = tx_nibble[command  & 0xF];
  tx_buf[9] = tx_nibble[room  & 0xF];
   //enable timer 2 interrupts
  TIMSK2 |= (1 << OCIE2A);
  tx_msg_active = true;
}

/**
  Set things up to transmit LightWaveRF 434Mhz messages
**/
void lwtx_setup(int pin, byte repeats, byte invert, int uSec) {
   if(EEPROMaddr >= 0) {
      for(int i=0; i<5; i++) {
        tx_buf[i+4] = EEPROM.read(EEPROMaddr+i);
      }
   }
  if(pin !=0) {
    tx_pin = pin;
  }
  if(repeats > 0 && repeats < 40) {
    tx_repeats = repeats;
  }
  if(invert != 0) {
    txon = 0;
    txoff = 1;
  } else {
    txon = 1;
    txoff = 0;
  }

  byte clock;
  if (uSec > 32 && uSec < 1000) {
    clock = (uSec / 4) - 1;
  } else {
    //default 140 uSec
    clock = 34;
  }
  pinMode(tx_pin,OUTPUT);
  digitalWrite(tx_pin, txoff);
  cli();//stop interrupts

  //set timer2 interrupt at  clock uSec (default 140)
  TCCR2A = 0;// set entire TCCR2A register to 0
  TCCR2B = 0;// same for TCCR2B
  TCNT2  = 0;//initialize counter value to 0
  // set compare match register for clock uSec
  OCR2A = clock;// = 16MHz Prescale to 4 uSec * (counter+1)
  // turn on CTC mode
  TCCR2A |= (1 << WGM21);
  // Set CS11 bit for 64 prescaler
  TCCR2B |= (1 << CS22);   
  // disable timer compare interrupt
  TIMSK2 &= ~(1 << OCIE2A);
  sei();//enable interrupts
}

void lwtx_setTickCounts( byte lowCount, byte highCount, byte trailCount, byte gapCount) {
     tx_low_count = lowCount;
     tx_high_count = highCount;
     tx_trail_count = trailCount;
     tx_gap_count = gapCount;
}

void lwtx_setGapMultiplier(byte gapMultiplier) {
   tx_gap_multiplier = gapMultiplier;
}

    // LxTx.h
//
// LightwaveRF 434MHz tx interface for Arduino
// 
// Author: Bob Tidey (robert@tideys.net)

#include <Arduino.h>
#include <../EEPROM/EEPROM.h>

//Sets up basic parameters must be called at least once
extern void lwtx_setup(int pin, byte repeats, byte invert, int uSec);

//Allows changing basic tick counts from their defaults
extern void lwtx_setTickCounts( byte lowCount, byte highCount, byte trailCount, byte gapCount);

//Allws multiplying the gap period for creating very large gaps
extern void lwtx_setGapMultiplier(byte gapMultiplier);

// determines whether incoming data or should be translated from nibble data
extern void lwtx_settranslate(boolean txtranslate);

//Checks whether tx is free to accept a new message
extern boolean lwtx_free();

//Basic send of new 10 char message, not normally needed if setaddr and cmd are used.
extern void lwtx_send(byte* msg);

//Sets up 5 char address which will be used to form messages for lwtx_cmd
extern void lwtx_setaddr(byte* addr);

//Send Command
extern void lwtx_cmd(byte command, byte parameter, byte room, byte device);

Thanks if you can!

bevangg, I will take a look but this library makes use of hardware timers so it may be more complicated, if possible. :smile:

bevangg, the library you posted will take some time to port. Have you considered another library by lawrie posted on his github. I can most likely port that one more quickly.

Thanks for the prompt reply peekay123. If it is possible to port Lawrie’s library then I am sure I could find a way to incorporate it into my work. I have not had time to have a proper look at it yet so will get back to you when I have done so.
Best regards

bevangg, take a look and let me know if it will do the job for you. I will look into porting Lawrie’s library.

@bevangg, the Lawrie library is fairly straight forward to port so let me know if you are still interested. :smile:

Hi peekay
I have been trying to get Lawrie’s library to work but have drawn a blank. Using exactly the same set-ups that work with the original library from Bob Tidey, I cannot receive messages from Lawrie’s lightwaverf library. I have sent him an email asking for advice.
Please bear with me, I await his reply if any.
Regards

@bevangg, the receiver setup call is:

void lw_rx_setup(int rx_pin, int interrupt) {
  lw_rx_pin = rx_pin;
  pinMode(lw_rx_pin,INPUT);
  attachInterrupt(interrupt,lw_process_bits,CHANGE);
} 

It is important to note that the way Arduino defines its pins and interrupts is different than that of the Spark. So the default lw_setup() call in the examples:

/**
  Set things up to transmit and receive LightwaveRF 434Mhz messages using default values
**/
void lw_setup() {
  lw_setup(3, 2, 0);
}

will NOT work with the Spark. Did you change the values to, for examplem lw_setup (D3, D2, D2)? This specifies pint D3 as tx, pin D2 as rx and interrupt on pin D2.

Hi peekay
I don’t have my sparks yet, there has been a problem with paypal so I will have to wait. I can however test with my due boards.
Do you think the library would work without any porting with that modification? And is the (D3,D2,D2) setup applicable to any due board? I tried that and it would not compile for my iduino due.
I received a reply from Lawrie and he explained that cheap ebay receiver modules were known not to work with his library. I tried it with a different more expensive module on a completed project and it worked, in the sense that I got messages on the serial monitor.
The conclusion is that yes, Lawrie’s library does work and would be a great thing to port for the spark for home automation projects.
Regards

@bevangg, the code should work with the unmodified Arduino library. I am not surprised about the cheaper versions. Let me know if you get it working with your Due. Also, when you get your Spark, we’ll try the modified library. :smile:

OK I will try it after work tomorrow and let you know how it goes.
Cheers

Hi
Update: I was beiing stupid, the (D3,D2,D2) is presumably specific to the spark. When reverted to (3,2,0) and sei()/cli() substituted with interrupt/nointerrupt it compiled but no output. It could be that interrupt should be set to 2 as all due pins have interrupt. Also I forgot that the data from the receiver would be 5v so may have blown a due up.
The fact that it compiles is reason for hope, I am waiting for parts to make a voltage divider schottkey to drop 5 to 3.3 from the radio and will try again. Luckily I have got a spare due if the first one is dead.

Hi
It is all working now. I did what I said in the last post using ie (3,2,2) for pin set-up in LightwaveRF.cpp, sei()/cli() substituted with interrupt/nointerrupt and dropping the signal from the receiver to 3.3 volts. I have not fully tested it yet but get serial output of lwrf signals so it is definitely working to some degree.
Thanks peekay for your help, I will post again when the sparks arrive and are tested.

Hi
The sparks arrived yesterday and I got one set up on line etc. I have tried to upload Lawrie’s lightwaverf example and libraries and get a compile error. Here is the code:

// LightwaveRF.h
//
// LightwaveRF 434MHz interface for Arduino
// 
// Author: Lawrie Griffiths (lawrie.griffiths@ntlworld.com)
// Copyright (C) 2012 Lawrie Griffiths

//#include <Arduino.h>

#define LW_OFF 0
#define LW_ON 1
#define LW_MOOD 2
#define LW_LOCK 4

extern void lw_tx_setup(int tx_pin);

extern void lw_rx_setup(int rx_pin, int interrupt);

extern boolean lw_setup(int tx_pin, int rx_pin, int interrupt);

extern void lw_setup();

extern void lw_rx_wait();

extern boolean lw_have_message();

extern boolean lw_get_message(byte* buf, byte* len);

extern void lw_send(byte* msg);

extern void lw_cmd(byte level, byte channel, byte cmd, byte* id);

extern void lw_get_error_stats(long *inv);




// LightwaveRF.cpp
//
// LightwaveRF 434MHz interface for Arduino
// 
// Author: Lawrie Griffiths (lawrie.griffiths@ntlworld.com)
// Copyright (C) 2013 Lawrie Griffiths

//#include <LightwaveRF.h>

static byte lw_nibble[] = {0xF6,0xEE,0xED,0xEB,0xDE,0xDD,0xDB,0xBE,
                     0xBD,0xBB,0xB7,0x7E,0x7D,0x7B,0x77,0x6F};

static int lw_rx_pin;
static int lw_tx_pin;

static volatile boolean lw_got_message = false; // true when full message received
static const byte lw_msg_len = 10; // the expected length of the message
static byte lw_msg[lw_msg_len]; // the message received

static byte lw_byte; // The current byte
static byte lw_num_bits = 0; // number of bits in the current byte
static unsigned long lw_prev; // time of previous pulse
static volatile boolean lw_p_started = false; // packet started
static boolean lw_b_started = false; // byte started
static byte lw_num_bytes = 0; // number of bytes received 

static const int lw_bit_delay = 560;
static const byte lw_repeats = 12; // Number of repeats of message sent

static long lw_num_invalid_packets[4];

/**
  Pin change interrupt routine that identifies 1 and 0 LightwaveRF bits
  and constructs a message when a valid packet of data is received.
**/
void lw_process_bits() { 
  // Don't process bits when a message is already ready
  if (lw_got_message) return;
  
  byte v = digitalRead(lw_rx_pin); // the current value
  unsigned long curr = micros(); // the current time in microseconds
  
  // Calculate pulse duration in 50 microsecond units
  unsigned int dur = (curr-lw_prev)/50;
  lw_prev = curr;
  
  // See if pulse corresponds to expected bit length
  if (dur < 6) {
    // inter 1 bit gap - do nothing
  } else if (dur < 11) {
    // potential 1 bit
    if (!v) { // value now zero as 1 pulse ended
      // 1 bit
      if (!lw_p_started) {
        // Start of message
        lw_p_started = true;
        lw_b_started = false;
        lw_num_bytes = 0;
      } else if (!lw_b_started) {
        // byte started
        lw_b_started = true;
        lw_num_bits = 0;
        lw_byte = 0;
      } else {
        // a valid 1 bit
        lw_byte = (lw_byte << 1) | 1;
        if (++lw_num_bits == 8) { // Test for complete byte
		  // Add the byte to the message
		  lw_b_started = false;
		  lw_msg[lw_num_bytes++] = lw_byte;
        }
      }
    } else {
      // Too short for a zero bit
      lw_p_started = false;
	  if (lw_num_bytes > 0) lw_num_invalid_packets[0]++;
    }
  } else if (dur > 20 && dur < 28) {
    // potential 0 bit
    if (v) {
      // 0 bit
      if (!lw_b_started) {
        // Zero bit where byte start bit expected
        lw_p_started = false;
		if (lw_num_bytes > 0) lw_num_invalid_packets[1]++;
      } else if (lw_p_started) {
        // Valid 0 bit
        lw_byte = (lw_byte << 1);
        if (++lw_num_bits == 8) {
          // Add the byte to the message
          lw_msg[lw_num_bytes++] = lw_byte;
          lw_b_started = false;
        }
      }
    } else {
      // Too long for a 1 bit
      lw_p_started = false;
	  if (lw_num_bytes > 0) lw_num_invalid_packets[2]++;
    }
  } else {
     // Not a valid length for a bit
	 if (lw_p_started && lw_num_bytes > 0) lw_num_invalid_packets[3]++;
	 lw_p_started = false;
  }
  
  // See if we have the whole message
  if (lw_p_started && lw_num_bytes == lw_msg_len) {
    lw_got_message = true;
    lw_p_started = false;
  }
}

void lw_get_error_stats(long* inv) {
  for(int i=0;i<4;i++) inv[i] = lw_num_invalid_packets[i];
}


/**
  Wait for a message to arrive
**/
void lw_rx_wait()
{
    while (!lw_got_message);
}

/**
  Test if a message has arrived
**/
boolean lw_have_message()
{
    return lw_got_message;
}

/**
  Transfer a message to user buffer
**/
boolean lw_get_message(byte  *buf, byte *len) {
  if (!lw_got_message) return false;
  
  // Buffer length must be 10
  if (*len != lw_msg_len) return false;
  
  memcpy(buf,lw_msg,lw_msg_len);

  lw_got_message = false;
  return true;
}

/**
  Set things up to transmit LightwaveRF 434Mhz messages using the pin specified
**/
void lw_tx_setup(int tx_pin) {
  lw_tx_pin = tx_pin;
  pinMode(lw_tx_pin,OUTPUT);
}

/**
  Set things up to receive LightwaveRF 434Mhz messages using the values specified
**/
void lw_rx_setup(int rx_pin, int interrupt) {
  lw_rx_pin = rx_pin;
  pinMode(lw_rx_pin,INPUT);
  attachInterrupt(interrupt,lw_process_bits,CHANGE);
}

/**
  Set things up to transmit and receive LightwaveRF 434Mhz messages using the values specified
**/
boolean lw_setup(int tx_pin, int rx_pin, int interrupt) {
  if(tx_pin == rx_pin) {
    return false;
  }
  
  lw_tx_setup(tx_pin);
  lw_rx_setup(rx_pin, interrupt);
  
  return true;
}

/**
  Set things up to transmit and receive LightwaveRF 434Mhz messages using default values
**/
void lw_setup() {
  lw_setup(D1, D0, D0);
}

/**
Transmit a 1 or 0 bit to a LightwaveRF device
**/
void lw_send_bit(byte b) {
  delayMicroseconds(25);
  digitalWrite(lw_tx_pin,b);
  delayMicroseconds(lw_bit_delay/2);
  digitalWrite(lw_tx_pin,LOW);
  delayMicroseconds(lw_bit_delay/2);
  
  if (b == LOW) {
    delayMicroseconds(300);
  }
}

/**
  Send a LightwaveRF byte
**/
void lw_tx_byte(byte b) {
  lw_send_bit(HIGH);

  for (byte mask = B10000000; mask; mask >>= 1) {
    lw_send_bit(b & mask);
  }
}

/**
  Send a LightwaveRF message
**/
void lw_send(byte* msg) {
  noInterrupts();
  for(byte j=0;j<lw_repeats;j++) {
    // send a start bit
    lw_send_bit(HIGH);
    
	// Send the 10 bytes
    for(byte i=0;i<lw_msg_len;i++) lw_tx_byte(msg[i]);
    
    // send end bit
    lw_send_bit(HIGH);
	
	// Delay between repeats
    delayMicroseconds(10250);
  } 
  interrupts();  
}

/**
  Send a LightwaveRF command
**/
void lw_cmd(byte level, byte channel, byte cmd, byte* id) {
  byte msg[10];
  
  msg[0] = lw_nibble[level >> 4];
  msg[1] = lw_nibble[level & 0xF];
  msg[2] = lw_nibble[channel];
  msg[3] = lw_nibble[cmd];
  
  for(int i=0;i<6;i++) {
    msg[4+i] = id[i];
  }
  lw_send(msg);
}




void setup() {
  lw_setup();
  Serial.begin(57600);
  Serial.println(F("Ready"));
}

void loop() {
  byte msg[10];
  byte len = 10;
  
  lw_rx_wait();
  lw_get_message(msg,&len);
  printMsg(msg, len);
}

void printMsg(byte *msg, byte len) {
  for(int i=0;i<len;i++) {
    Serial.print(msg[i], DEC);
    Serial.print(" ");
  }
  Serial.println();
}

This is the error that I get:
In file included from …/inc/spark_wiring.h:30:0,
from …/inc/application.h:31,
from /lw2.cpp:2:
…/…/core-common-lib/SPARK_Firmware_Driver/inc/config.h:12:2: warning: #warning “Defaulting to Release Build” [-Wcpp]
/lw2.cpp:4:1: error: expected unqualified-id before ‘else’
/lw2.cpp: In function ‘void lw_tx_byte(byte)’:
/lw2.cpp:245:20: error: ‘B10000000’ was not declared in this scope
make: *** [/lw2.o] Error 1

It looks good to have got this far. One issue that I have found with the example is that the following statement disables the arduino until a message is received:

void lw_rx_wait()
{
    while (!lw_got_message);
}

Is there any easy way around that?
Cheers

The error you are getting is because Arduino allows this non-standard way to write boolean values for integer types "B10000000" instead of the standard 0xb10000000. If you make that change, it should compile that part.

Your question about the while loop is harder to answer without knowing more about the code. Maybe someone that has use the LightwaveRF library can answer that one!

@bevangg, I will have the library ported shortly. Stay tuned! :smile:

UPDATE: I have posted the Lightwave library on my github. Make sure to read the README for the default rx/tx pin assignment. Test the code to start with so we know it works. Then we can look at the while loop issue after that (I have some ideas!). Keep me posted! :smile:

Hi peekay
Brilliant! It compiles and works with the lwreceive example code, I tested it by latching the on-board led when it received a message and it definitely works. I have tried to use the spark cli to see what it is receiving with serial prints but get nothing (board listening and flashing blue) so looks like a night of googling to work it out. Presumably there is a way to serial monitor over wifi, again I will see what google knows about that. Seems that there is very little info out there at the moment, no doubt there will be more soon as the spark community grows.
As-well as these minor challenges I now have to get the transmission side worked out.
Thanks for porting the library, I am sure it will be very useful to anybody wanting to put together a very cheap automation and / or security system. One spark could control countless lower powered arduinos over lightwaverf and allow to control and program the whole thing remotely.

@bevangg, the challenge with using the serial port for monitoring is somehow synchronizing the start of the code with the time you open your console/CLI. You can add this code after your Serial.begin() in setup() to allow you to hit a key before proceeding:

while(!Serial.available()) SPARK_WLAN_Loop();

Don’t hesitate to sprinkle some Serial.print() debug message around the code to get an idea of what’s going on.

I noticed you seem to have a buffer IC acting as a level-shifter I assume. Which part is it?

Hi peekay
Well spotted, it is a 74HC4050 6 channel voltage down level shifter. Rather more elegant and trustworthy than the schottky arrangement and uses less space on the board if you were using 6 5volt inputs. I was planning against not being able to transmit or receive with the spark due to the library and decided that I could use an Arduino Nano as a slave over I2C. I should have done more research and got a bidirectional IC with four IOs. I read somewhere that all pins on the spark except D2 are 5 volt resistant but would not want to test it. Next challenge is to make a level up shifter with a mosfet for the transmitter but not sure if I have the correct type of mosfet in my hoard of useless parts . Until that is done testing transmission will have to wait.
Thanks for the advice on the serial monitor, I will give it a try
Regards

Ok, I have got the serial monitor working with arduino ide as per your instructions. It should not be too difficult to ajax that but being lazy I will see if somebody has done it already.
For now I will concentrate on the transmission side as this is crucial for the envisaged system to work as intended although I have got a fallback using a nano to transmit.
Edit: turns out I have not got any 2N7000 mosfets, they are on order now from banggood.com, so should have them within two weeks and at ebay prices. Will re-prioritize to ajax lightwaverf output until they arrive.
Does this circuit look ok? I have seen it in numerous places but am not sure if it should be bi-directional for a transmitter.