/*
rf433.cpp - Arduino Library for RF433.
Copyright 2013-2014 - Laurent Menu-Kerforn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "Arduino.h"
#include "rf433.h"
/* ==================================================
_
| |__ __ _ ___ ___
| '_ \ / _` / __|/ _ \
| |_) | (_| \__ \ __/
|_.__/ \__,_|___/\___|
===================================================== */
rf433::rf433() {
powerled=-1;
powerpin=-1;
activityled=-1;
trans=NULL;
transcount=0;
maxtrans=0;
}
int rf433::setbuffer(rf433trans *buftrans,int bufsize) {
trans=buftrans;
maxtrans=bufsize;
transcount=0;
return 1;
}
int rf433::settranscount(int count) {
transcount=count;
return 1;
}
int rf433::gettranscount() {
return transcount;
}
int rf433::init() {
return reset();
}
word rf433::micro2ticks(unsigned long us){
unsigned int ret;
us>>=2; //division par 4
if(us>65535) return 0;
ret=us;
return ret;}
unsigned long rf433::ticks2micro(word ticks){
unsigned long ret=(unsigned long)ticks;
ret<<=2; //division par 4
return ret;}
int rf433::poweron() {
setpower(HIGH);
setpowerled(HIGH);
return 1;}
int rf433::poweroff(){
setpower(LOW);
setpowerled(LOW);
return 1;}
int rf433::setactivityledpin(int pin) {
activityled=pin;
if(pin>=0) {
pinMode(activityled,OUTPUT);
digitalWrite(activityled,LOW);
};
return 1;
}
int rf433::setpowerpin(int pin) {
powerpin=pin;
if(pin>=0) {
pinMode(powerpin,OUTPUT);
digitalWrite(powerpin,LOW);
};
return 1;}
int rf433::setpowerledpin(int pin) {
powerled=pin;
if(pin>=0) {
pinMode(powerled,OUTPUT);
digitalWrite(powerled,LOW);
};
return 1;
}
int rf433::setpowerled(int level) {
if(powerled>=0) digitalWrite(powerled,level);
return 1;
}
int rf433::setactivityled(int level) {
if(activityled>=0) digitalWrite(activityled,level);
return 1;
}
int rf433::setpower(int level) {
if(powerpin>=0) digitalWrite(powerpin,level);
return 1;
}
/* debug */
/*
unsigned long collect[256];
int cc=0;
*/
/* fin debug */
/* exemple utilisation timer 1
cli();
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 300;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
static int min=10;
static int max=160;
static int step=5;
static int level=min;
static int inc=step;
level+=inc;
if(level255) {inc=-step;level=max;};
analogWrite(8,level);
}
*/
/* ==================================================
_
_ __ ___ ___ ___(_)_ _____
| '__/ _ \/ __/ _ \ \ \ / / _ \
| | | __/ (_| __/ |\ V / __/
|_| \___|\___\___|_| \_/ \___|
===================================================== */
rf433r::rf433r() {
minsiglen=_RF_MINSIGTICKS;
minrxtrans=_RF_MINRXTRANS;
}
int rf433r::setminsiglen(long len) {
minsiglen=micro2ticks(len);
return 1;
}
int rf433r::enableint() {
cli();
_RF_TIMSK|=(1<<_RF_ICIE); //interruption sur Capture Interrupt
// pin 8 ICP1
sei();
return 1;
}
int rf433r::disableint() {
cli();
_RF_TIMSK&=~(1<<_RF_ICIE); //interruption sur Capture Interrupt
sei();
return 1;
}
int rf433r::dump() {
Serial.println("======================");
Serial.print("TCNT : "); Serial.println(_RF_TCNT);
Serial.print("TCCRA : "); Serial.println(_RF_TCCRA);
Serial.print("TCCRB : "); Serial.println(_RF_TCCRB);
Serial.print("TIMSK : "); Serial.println(_RF_TIMSK);
Serial.print("TIFR : "); Serial.println(_RF_TIFR);
Serial.print("ACSR : "); Serial.println(_RF_ACSR);
Serial.print("activityled : "); Serial.println(activityled);
Serial.print("powerpin : "); Serial.println(powerpin);
Serial.print("powerled : "); Serial.println(powerled);
Serial.print("maxtrans : "); Serial.println(maxtrans);
Serial.print("transcount : "); Serial.println(transcount);
Serial.print("minsiglen : "); Serial.println(minsiglen);
Serial.print("_RF_ICES : "); Serial.println(_RF_ICES);
Serial.print("_RF_ICF : "); Serial.println(_RF_ICF);
Serial.print("_RF_ICIE : "); Serial.println(_RF_ICIE);
Serial.print("_RF_ACIC : "); Serial.println(_RF_ACIC);
for(int i=0;i1) transcount--;
//enregistrement si dans les clous
if(transcount=maxtrans);
}
int rf433r::start() {
// Serial.println("START !");
cli();
transcount=0;
cli();
_RF_TCCRB|=(1<<_RF_ICES); // front montant
_RF_TIFR|=(1<< _RF_ICF); //effacement interruption en cours
_RF_TIMSK|=(1<<_RF_ICIE); //autrisation interuption
_RF_TCNT=0; //mise à 0 du compteur
sei();
return 1;
}
int rf433r::stop() {
disableint();
setactivityled(LOW);
return 1;
}
/* ==================================================
_ _
___ _ __ ___ (_) |_
/ _ \ '_ ` _ \| | __|
| __/ | | | | | | |_
\___|_| |_| |_|_|\__|
===================================================== */
int rf433t::setemitpin(int pin) {
emitpin=pin;
pinMode(emitpin,OUTPUT);
digitalWrite(emitpin,LOW);
return 1;}
int rf433t::slowit(){
cli();
_RF_TCCRB|=(1<< _RF_CS2)|(1<<_RF_CS0); //prescaler=1024
sei();
return 1;
}
int rf433t::reset(){
// Serial.println("RESET ******************************************");
// NE JAMAIS METTRE LE SETUP DES I/O DANS LE CONSTRUCTEUR !
// ELLES SONT RESETÉES AU DEFAUT AVANT LA FONCTION setup()
cli();
_RF_TIMSK=0;
_RF_TCCRA=0;
_RF_TCCRB=0;
_RF_TCCRB|=(1<<_RF_WGM2); //CTC mode
_RF_TCCRB|=(1<< _RF_CS1)|(1<<_RF_CS0); //prescaler=64
sei();
setactivityledpin(activityled);
setpowerpin(powerpin);
setpowerledpin(powerled);
setemitpin(emitpin);
// calcul conversion µs/ticks
// une µs =1 megaherz
// prescale 8 : 2MHz, 2 ticks pour une µs, pb : 32768 delay maximum
// prescale 64 : 250kHz, 4 µs pour 1 tick
// prescale 256 : 31,250 kHz 32 µs pour 1 tick
// prescale 20124 : 3906 Hz, 256µs pour 1 tick
// On part sur un prescale de 64, on peut avoir le nombre de ticks en shiftant de 2 à droite ( >> 2 )
// la précision ) 4 µs près est correcte
// le délai max est de 65*4 µs maximum
resetemit();
return 1;
}
int rf433t::resetemit() {
//on commence par arrêter l'envoi en cours si il y en a un
disableint();
_RF_OCRA = 50000; //200000 µs 0,2 secondes
status=0;
setactivityled(LOW);
digitalWrite(emitpin,LOW);
transindex=0;
transcount=0;
repeatcount=0;
trans[0].level=0;
trans[0].ticks=0;
return 1;
}
rf433t::rf433t(int pin) {
ordor[0]=0;
ordor[1]=0;
coeff[0]=60;
coeff[1]=60;
repeat=1;
emitpin=pin;
}
int rf433t::isrunning() {
return status;
}
int rf433t::waittxend() {
while(isrunning());
return 1;
}
int rf433t::recus(int level,unsigned long us) {
if(transcount+2>maxtrans) return 0;
trans[transcount].level=level;
trans[transcount].ticks=micro2ticks(us);
transcount++;
return 1;
}
int rf433t::recbit(int level,int count) {
unsigned long us;
int levelindex;
levelindex=(level==LOW)? 0:1;
us=count*coeff[levelindex]+ordor[levelindex];
return recus(level,us);
}
int rf433t::bufferize(char *code) {
char *p;
int level;
int first=1;
int curlevel=-1;
int curlevelcount=0;
// reset();
resetemit();
addheader();
for(p=code;*p;p++) {
level=(*p=='0')? LOW:HIGH;
if(!first && level!=curlevel) {
//enregistrement transisiton précédente
recbit(curlevel,curlevelcount);
curlevelcount=0;
};
curlevel=level;
curlevelcount++;
first=0;
};
if(!first) recbit(curlevel,curlevelcount);
addtailer();
return transcount;
}
int rf433t::enableint(){
cli();
_RF_TIMSK|=(1<<_RF_OCIEA); //interruption sur timer A
sei();
return 1;}
int rf433t::disableint(){
cli();
_RF_TIMSK&=~(1<<_RF_OCIEA); //pas d'interruption sur timer A
sei();
return 1;}
int rf433t::dump(){
Serial.println("======================");
Serial.print("TCCRA : "); Serial.println(_RF_TCCRA);
Serial.print("TCCRB : "); Serial.println(_RF_TCCRB);
Serial.print("TIMSK : "); Serial.println(_RF_TIMSK);
Serial.print("TIFR : "); Serial.println(_RF_TIFR);
Serial.print("status : "); Serial.println(status);
Serial.print("repeat : "); Serial.println(repeat);
Serial.print("repeatcount : "); Serial.println(repeatcount);
Serial.print("maxtrans : "); Serial.println(maxtrans);
Serial.print("transindex : "); Serial.println(transindex);
Serial.print("transcount : "); Serial.println(transcount);
Serial.print("emitpin : "); Serial.println(emitpin);
Serial.print("activityled : "); Serial.println(activityled);
Serial.print("powerpin : "); Serial.println(powerpin);
Serial.print("powerled : "); Serial.println(powerled);
for(int i=0;i=transcount) {
repeatcount++;
if(repeat && (stopit || repeatcount>=repeat)) {
// arret
status=0;
_RF_TIMSK&=~(1<<_RF_OCIEA); //pas d'interruption sur timer A
//pas d'appel de la methode disableint pour eviter de croiser sei/cli
stopit=0;
return 1;
}
transindex=0;
};
_RF_OCRA=trans[transindex].ticks;
/* debug */
/*
// collect[cc++]=trans[transindex].ticks;
//collect[cc++]=millis();
collect[cc++]=micros();
*/
/* fin debug */
digitalWrite(emitpin,trans[transindex].level);
setactivityled(trans[transindex].level);
return 1;
}
int rf433t::addheader(){
//utilisation de recbit(level,count) ou recus(level, microseconds)
return 1;}
int rf433t::addtailer(){
//utilisation de recbit(level,count) ou recus(level, microseconds)
recus(LOW,(unsigned long)64); //retour à 0 systématique par défaut
return 1;}
int rf433t::emit(char *string){
return (bufferize(string))? start():0;
}