goodwatch/firmware/apps/ook.c
2018-10-08 21:19:22 -04:00

203 lines
5.7 KiB
C

/*! \file ook.c
\brief Example OOK Application
Howdy y'all,
This is a quick little comm demo that sends OOK commands to INSMA
Modules. Additional remotes can be added without forking this
module by placing their data rates (MDMCFG4 and MDMCFG3) and packets
into the OOKBUTTONS array of your config.h.
You can buy this particular transmitter from Amazon as ``INSMA
433Mhz Wireless RF Switch 328ft Long Range DC 12V 4CH Channel
Wireless Remote Control Switch, DC12V Relay Receiver Module,
Transmitter Toggle Switch RF Relay (2 Transmitter & 1 Receiver).''
These packets are based on my own device, but you can use the
learning button to train your radio to it. Bits and timings were
initially reversed with Universal Radio Hacker, then a single packet
was prototyped in Python through the Monitor feature. Once this
packet was properly compared to the original, a steady stream of
packets was created by the ook_packettx() callback.
The 'bits' are 341 µs long for a symbol rate of 2.93207 kilobaud,
but because the protocol is designed in terms of short and long
pulses, an E nybble represents a long pulse and an 8 represents a
short pulse.
These are the four packets from my remote:
A 0000e8e8ee88e88ee888eee8888e8000
B 0000e8e8ee88e88ee888eee888e88000
C 0000e8e8ee88e88ee888eee88e888000
D 0000e8e8ee88e88ee888eee8e8888000
There is no preamble; rather, packets begin on a rising edge in the
third byte. The receiver expects many packets in a row, so we start
a new transmittion in the callback after each transmission and we
raise the main clock frequency to be able to react in time. For
other receivers, you might be able to get away with a single
transmission.
Further details and a tutorial for adding your own remote are in the
wiki.
https://github.com/travisgoodspeed/goodwatch/wiki/OOK_Example
--Travis
*/
#include<stdio.h>
#include<string.h>
#include<msp430.h>
#include "api.h"
//Fixed packet length is easier on our packet library.
#define LEN 16
/* Settings were prototyped first in Python. This is basic OOK with
no preamble, no CRC, and 341µs symbol times.
*/
static const uint8_t ook_settings[]={
//Change these to change the rate.
//MDMCFG4, OOKMDMCFG4, // Modem Configuration
//MDMCFG3, OOKMDMCFG3, // Modem Configuration
//These rest are consistent for all OOK emulation.
MDMCFG2, 0x30, // Modem Configuration, no sync
FREND0 , 0x11, // Front End TX Configuration
FSCAL3 , 0xE9, // Frequency Synthesizer Calibration
FSCAL2 , 0x2A, // Frequency Synthesizer Calibration
FSCAL1 , 0x00, // Frequency Synthesizer Calibration
FSCAL0 , 0x1F, // Frequency Synthesizer Calibration
PKTCTRL0, 0x00, // Packet automation control, fixed length without CRC.
PKTLEN, LEN, // PKTLEN Packet length.
0,0
};
//! Array of keys for button pressing.
static const char * const button_array[] = {
/* These were recorded with Universal Radio Hacker (URH). You might
need to adjust both these packets and the symbol periods defined
above. */
OOKBUTTONS
};
/*
//! Local function that returns an OOK array index from a button. -1 on failure.
static int button2index(char c){
//For now, only numbers. Might change this later to have even rows of four buttons.
if(c<='9' && c>='0'){
return c-'0';
}
//Otherwise failure.
return -1;
}
*/
//! Handle an incoming packet.
void ook_packetrx(uint8_t *packet, int len){
printf("Not yet supported.\n");
}
static char lastch=0;
//! Send a packet.
static void transmit(int index){
//Packet begins on the third byte.
packet_tx((uint8_t*) button_array[index]+2,
LEN);
}
//! Set the rate.
static void setrate(int index){
//First two bytes are the rate.
radio_writereg(MDMCFG4, ((uint8_t*) button_array[index])[0]);
radio_writereg(MDMCFG3, ((uint8_t*) button_array[index])[1]);
}
//! Called after a transmission, or on a button press.
void ook_packettx(){
/* Schedule next packet if a number is being held. We already set
the bitrate in the keypress handler.
*/
if(lastch<='9' && lastch>='0'){
transmit(lastch-'0');
}
}
//! Enter the OOK transmitter application.
void ook_init(){
/* Skip this application if we haven't got a radio.
*/
if(!has_radio){
app_next();
}
lcd_string(" OOK");
printf("%d button entries are available.\n", sizeof(button_array)/2);
}
//! Exit the OOK application.
int ook_exit(){
//Cut the radio off.
radio_off();
//Allow the exit.
return 0;
}
//! Draw the OOK screen.
void ook_draw(){
int state=radio_getstate();
switch(state){
case 0:
case 1:
//lcd_string(" OOK");
break;
case 19: //RX IDLE between transmit packets.
lcd_string("TRANSMIT");
break;
case 22: //TX_OVERFLOW
printf("TX Overflow.\n");
radio_strobe(RF_SIDLE);
break;
default:
lcd_hex(state);
break;
}
}
//! Keypress handler for the ook applet.
int ook_keypress(char ch){
/* When a key is first pressed, we call ook_packettx() to kick off a
transmission. That function is also the callback from the packet
library, so it will keep running in a loop until the key is
released.
*/
if( (lastch=ch) && ch>='0' && ch<='9' ){
//Radio settings.
radio_on();
radio_writesettings(ook_settings);
setrate(ch-'0'); //First two bytes are the packet rate.
radio_writepower(0x25);
//Set a frequency manually rather than using the codeplug.
radio_setfreq(433960000);
//This handler will be called back as the packet finished transmission.
ook_packettx();
}else{
//Shut down the radio when the button is released.
radio_off();
lcd_zero(); //Clear the clock and radio indicators.
lcd_string(" OOK");
}
return 0;
}