denny9167
Member level 1
I'm trying to implement SIRC protocol using OOK transmission, Has it been attempted before,or any drawbacks? Ive posted my TX/RX below. The decoder works great using a 40Khz carrier, but Im not sure what, if any changes are needed using ON/OFF keying. I welcome any input. BTW the transmitter has been built and tested with a logic analyzer. The receiver has only been built and not tested.
Code:
/*
* File: TX_SIRC.c
* Author: Denny Brown
* Description: Handheld RF Transmitter
* Device: PIC12F615
*/
#include <xc.h>
#include <stdint.h>
//Configuration Bit Settings
// CONFIG
#pragma config FOSC = INTOSCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config IOSCFS = 8MHZ
#pragma config BOREN = ON
#define _XTAL_FREQ 8000000 // required for delay routines.
#define RF_OUT GPIObits.GPIO2 // RF Data IN is conntected to this port
#define KEY_1 GPIObits.GPIO0 //Switch pin definitions
#define KEY_2 GPIObits.GPIO1
#define LED GPIObits.GPIO5
#define ADDRESS 1
#define DATA_KEY_1 2
#define DATA_KEY_2 3
// The function takes two arguments, these get assigned to command and address
void sendFrame(uint8_t command,uint8_t address)
{ // Move / mask the bits around, so that we have 7 bits of command, then 5 bits of address
uint16_t u16Send=(((uint16_t)(address&0x1F))<<7)|(command&0x7F);
uint8_t uBitLoop;
//Start bit 2.4ms time
RF_OUT=1;
LED=1;
__delay_us(2400);
RF_OUT=0;
LED=0;
__delay_us(600);
// Start with u16Test having bit 11 set, then walk down to bit 0, when u16Test reaches 0 we're all done
for(uBitLoop=12 ; uBitLoop!=0 ; uBitLoop--,u16Send>>=1)
{ // Turn PWM on
RF_OUT=1;
LED=1;
__delay_us(600);
// If (u16Test&u16Send)!=0 then the bit to send is a 1, so send a long on pulse, otherwise send a short one
if (u16Send&0x01)
{ // It's a 1 so extend to a long pulse
__delay_us(1200-600);
}
// Either short or long pulse done, turn off pulse
RF_OUT=0;
LED=0;
// Wait gap (same for a 1 or 0)
__delay_us(600);
}
}
void __interrupt() swInt(void)
{
if (INTCONbits.GPIF) // check the interrupt on change flag
{
__delay_ms(2); //check for key de-bounce
if(!KEY_1) //check if the Key_1 is pressed (GPIO is low)
{
sendFrame(DATA_KEY_1,ADDRESS); //send the frame
while(!KEY_1) //if the key is still pressed
{
sendFrame(DATA_KEY_1,ADDRESS); //repeat the frame
}
INTCONbits.GPIF =0;
if(!KEY_2) //check if the Key_2 is pressed
{
sendFrame(DATA_KEY_2,ADDRESS); //send the frame
while(!KEY_2) //if the key is still pressed
{
sendFrame(DATA_KEY_2,ADDRESS); //repeat the frame
}
INTCONbits.GPIF =0; // clear the interrupt on change flag
}
}
void main()
{
CMCON0bits.CMON =0; // disable the comparator
ANSEL = 0x00; // all pin are Digital
TRISIO = 0x3; // Only GP2 is set to output rest are input
OPTION_REG = 0x5F; //pull-ups are enabled //timer0 clock source is internal
//timer0 pre-scaler is 1:1 (disabled "assigned to WDT")
WPU = 0x3; //week pull-ups are enabled for all switches.
GPIO = 0x3; //put hight to the latch value of each GPIO
IOC = 0x3; //interrupt on change
INTCONbits.GPIE = 1;
INTCONbits.GPIF = 0; // clear the external interrupt flag INTCONbits.PEIE = 1; // peripheral interrupt enable
INTCONbits.GIE = 1; // GLOBAL interrupt enable
for(;;)
{
SLEEP();
}
}
Code:
/*
* File: RX_SIRC.c
* Author: Denny Brown
*
* Created on June 1, 2022, 8:12 PM
*/
#include <xc.h>
#include <stdint.h>
// PIC12F615 Configuration Bit Settings
// CONFIG
#pragma config FOSC = INTOSCIO
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config IOSCFS = 8MHZ
#pragma config BOREN = ON
#define _XTAL_FREQ 8000000
#define LED1 GPIObits.GPIO5 // RF receive status indicator
#define LED2 GPIObits.GPIO4
#define RF_IN GPIObits.GPIO3 // RF DATA PORT
//=============================================================================
// RECEIVE_RF_PACKET
//=============================================================================
unsigned int overflow=0;
void receive_rf_packet(void)
{
//-------------------------------------------------------
// This function receives an RF packet of bytes in the pulse period
// encoded format. The packet must have 2 valid contiguous bytes
// global variables; address_byte and command_byte hold the byte result.
// Note: TMR0 runs at 500kHz frequency, That is why 200uS = 100 TMR0 pulse_time
//-------------------------------------------------------
unsigned int pulse_time;
unsigned char bitcount;
unsigned char command;
unsigned char address;
while(1){ // loop until it has received 2 contiguous RF bytes
command=0;
address=0;
//-----------------------------------------
// Get preamble - 2.4mS pulse,1.2mS space
while(RF_IN); // wait for input / edge
overflow =0;
TMR0 = 0; // and ready to record next period
while(!RF_IN); // wait for input \ edge
pulse_time=(overflow >>8) +TMR0;
if ((pulse_time > 0x80) && (pulse_time <0xB0)){ // grab the pulse time
//-----------------------------------------
// now we had a start pulse, record 7 command bits
for(bitcount = 0 ; bitcount < 7; bitcount++){ // 8 address bits
while(RF_IN); // wait for input / edge
overflow =0;
TMR0 = 0;
while(!RF_IN); // wait for input \ edge
pulse_time = (overflow >>8) + TMR0; // grab the pulse time!
command >>= 1; // shift
command &= 0x7F; // top bit zero
if (pulse_time> 0x40){
command ^= 0x80; // top bit 1
}
}
command >>=1; // shift 1 unused bit
command &= 0x7F; // clear top bit
//-----------------------------------------
// now record 5 address bits
for(bitcount = 0 ; bitcount < 5; bitcount++){ // 8 command bits
while(RF_IN); // wait for input / edge
overflow =0;
TMR0 = 0;
while(!RF_IN); // wait for input \ edge
pulse_time = (overflow >>8) + TMR0; // grab the pulse time!
address >>= 1; // shift
address &= 0x7F; // top bit zero
if (pulse_time> 0x40){
address ^= 0x80; // top bit 1
}
}
address >>= 3; // shift 3 unused bits
address &= 0x1F; // clear top 3 bits
if(address == 1){
if(command == 2){
LED1 = ~LED1;
__delay_ms(100);
}
if(command == 3){
LED2=~LED2;
__delay_ms(100);
}
}
}
}
}
//-----------------------------------------------------------------------------
// Timer0 interrupt
void __interrupt() ISR(void){
if (INTCONbits.T0IF) {
overflow++; // increment overflow
INTCONbits.T0IF = 0; // Clear Timer0 overflow interrupt flag
}
}
/* THE main source code starts here*/
void main()
{
CMCON0=0x7; // disable the comparator
ANSEL =0x00;
TRISIO3=1; // Only GP3 is set to input rest are out
TRISIO5=0;
OPTION_REG=0x81; //pull-ups disabled, 1:4 pre-scaler = 500kHz
INTCONbits.GIE = 1; // Global interrupt enable
INTCONbits.T0IE =1; // Timer0 interrupt enable
GPIO =0;
receive_rf_packet();
}
Last edited: