Skip to content

Instantly share code, notes, and snippets.

@pouriap
Created September 5, 2020 18:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pouriap/f0d6acd32039e6c8a971582f1c448e25 to your computer and use it in GitHub Desktop.
Save pouriap/f0d6acd32039e6c8a971582f1c448e25 to your computer and use it in GitHub Desktop.
#include "TinyRF.h"
//CRC-8 - based on the CRC8 formulas by Dallas/Maxim
//code released under the therms of the GNU GPL 3.0 license
byte crc8(byte data[], uint8_t len){
byte crc = 0x00;
while (len--)
{
byte extract = *data++;
for (byte tempI = 8; tempI; tempI--)
{
byte sum = (crc ^ extract) & 0x01;
crc >>= 1;
if (sum)
{
crc ^= 0x8C;
}
extract >>= 1;
}
}
return crc;
}
#ifndef TINYRF_H
#define TINYRF_H
#include "Arduino.h"
const uint8_t MAX_MSG_LEN = 255;
const unsigned int START_PULSE_DURATION = 3000;
const unsigned int ONE_PULSE_DURATION = 2000;
const unsigned int ZERO_PULSE_DURATION = 1500;
const unsigned int HIGH_PERIOD_DURATION = 1000;
//Function declarations
byte checksum8(byte data[], uint8_t len);
byte crc8(byte data[], uint8_t len);
#endif /* TINYRF_H */
#include "TinyRF_RX.h"
volatile bool transmitOngoing = false;
volatile uint8_t bufIndex = 0;
byte rcvdBytsBuf[RX_BUFFER_SIZE];
volatile unsigned long rcvdPulses[8];
volatile uint8_t numMsgsInBuffer = 0;
volatile uint8_t msgAddrInBuf = 0;
volatile uint8_t msgLen = 0;
uint8_t bufferReadIndex = 0;
volatile unsigned long lastTime = 0;
uint8_t rxPin = 2;
void setupReceiver(uint8_t pin){
rxPin = pin;
pinMode(rxPin, INPUT);
attachInterrupt(digitalPinToInterrupt(rxPin), interrupt_routine, FALLING);
}
inline bool process_received_byte(){
byte receivedData = 0x00;
for(uint8_t i=0; i<8; i++){
if(
rcvdPulses[i] > (ONE_PULSE_DURATION - TRIGER_ERROR)
&& rcvdPulses[i] < (ONE_PULSE_DURATION + TRIGER_ERROR)
){
receivedData |= (1<<i);
}
else if(
rcvdPulses[i] < (ZERO_PULSE_DURATION - TRIGER_ERROR)
|| rcvdPulses[i] > (ZERO_PULSE_DURATION + TRIGER_ERROR)
){
//this is noise = end of transmission
transmitOngoing = false;
if(msgLen>0){
rcvdBytsBuf[msgAddrInBuf] = msgLen;
numMsgsInBuffer++;
bufIndex++;
}
return false;
}
}
rcvdBytsBuf[++bufIndex] = receivedData;
msgLen++;
return true;
}
void interrupt_routine(){
static uint8_t pulse_count = 0;
unsigned long time = micros();
unsigned long pulseDuration = time - lastTime;
lastTime = time;
if(
pulseDuration > (START_PULSE_DURATION - TRIGER_ERROR)
&& pulseDuration < (START_PULSE_DURATION + START_PULSE_MAX_ERROR)
){
if(transmitOngoing){
rcvdBytsBuf[msgAddrInBuf] = msgLen;
numMsgsInBuffer++;
bufIndex++;
}
transmitOngoing = true;
pulse_count = 0;
msgAddrInBuf = bufIndex;
msgLen = 0;
}
else if(transmitOngoing){
rcvdPulses[pulse_count] = pulseDuration;
pulse_count++;
}
if(pulse_count == 8){
//todo: this doesn't need return type
process_received_byte();
pulse_count = 0;
}
}
byte getReceivedData(byte buf[]){
if(numMsgsInBuffer == 0){
return TINYRF_ERR_NO_DATA;
}
uint8_t msgLen = rcvdBytsBuf[bufferReadIndex];
bufferReadIndex++;
numMsgsInBuffer--;
if(msgLen == 0){
return TINYRF_ERR_NO_DATA;
}
//dataLen is the actual data, i.e. minus the CRC
uint8_t dataLen = msgLen - 1;
//copy the data from 'bufferReadIndex' until bufferReadIndex+dataLen
for(int i=0; i<dataLen; i++){
buf[i] = rcvdBytsBuf[bufferReadIndex++];
}
//crc
byte crcRcvd = rcvdBytsBuf[bufferReadIndex];
//go to next byte
bufferReadIndex++;
byte crcCalc = crc8(buf, dataLen);
if(crcRcvd != crcCalc){
#ifndef __AVR_ATtiny13__
Serial.print("BAD CRC: [");Serial.print((char*)buf);Serial.println("]");
Serial.print("crcRcvd: ");Serial.print(crcRcvd, HEX);Serial.print(" crcCalc: ");Serial.print(crcCalc, HEX);Serial.print(" len: ");Serial.println(dataLen);
#endif
return TINYRF_ERR_BAD_CRC;
}
return TINYRF_ERR_SUCCESS;
}
#ifndef TINYRF_RX_H
#define TINYRF_RX_H
#include "TinyRF.h"
//Constants
const uint8_t TINYRF_ERR_NO_DATA = 0;
const uint8_t TINYRF_ERR_BAD_CRC = 1;
const uint8_t TINYRF_ERR_SUCCESS = 2;
const uint16_t RX_BUFFER_SIZE = 256;
const int TRIGER_ERROR = 50;
const int START_PULSE_MAX_ERROR = 400;
void setupReceiver(uint8_t pin);
void interrupt_routine();
byte getReceivedData(byte buf[]);
#endif
#include "TinyRF_TX.h"
uint8_t txPin = 2;
void setupTransmitter(uint8_t pin){
txPin = pin;
pinMode(txPin, OUTPUT);
}
void send(byte* data, uint8_t len){
byte crc = crc8(data, len);
//preamble
for(int i=0; i<PREABMLE_DURATION; i++){
digitalWrite(txPin, LOW);
delayMicroseconds(200);
digitalWrite(txPin, HIGH);
delayMicroseconds(800);
}
//start pulse
digitalWrite(txPin, LOW);
delayMicroseconds(START_PULSE_DURATION - HIGH_PERIOD_DURATION);
digitalWrite(txPin, HIGH);
delayMicroseconds(HIGH_PERIOD_DURATION - 4); //-4 because digitalWrite takes ~4us
//data
for(uint8_t i=0; i<len; i++){
transmitByte(data[i]);
}
///crc
transmitByte(crc);
digitalWrite(txPin, LOW);
#if !defined(EOT_IN_RX) && !defined(EOT_NONE)
for(uint8_t i=0; i<10; i++){
delayMicroseconds(HIGH_PERIOD_DURATION/2);
digitalWrite(txPin, HIGH);
delayMicroseconds(HIGH_PERIOD_DURATION/2);
digitalWrite(txPin, LOW);
}
#endif
}
void transmitByte(byte _byte){
for(uint8_t i=0; i<8; i++){
//if 1
if(_byte & (1<<i)){
digitalWrite(txPin, LOW);
delayMicroseconds(ONE_PULSE_DURATION - HIGH_PERIOD_DURATION);
digitalWrite(txPin, HIGH);
delayMicroseconds(HIGH_PERIOD_DURATION - 4);
}
else{
digitalWrite(txPin, LOW);
delayMicroseconds(ZERO_PULSE_DURATION - HIGH_PERIOD_DURATION);
digitalWrite(txPin, HIGH);
delayMicroseconds(HIGH_PERIOD_DURATION - 4);
}
}
}
#ifndef TINYRF_TX_H
#define TINYRF_TX_H
#include "TinyRF.h"
const uint8_t PREABMLE_DURATION = 50;
//Function declarations
void setupTransmitter(uint8_t pin);
void send(byte data[], uint8_t len);
void transmitByte(byte _byte);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment