AskSin++
AskSinPP.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __ASKSINPP_h__
7 #define __ASKSINPP_h__
8 
9 #define ASKSIN_PLUS_PLUS_MAJOR 4
10 #define ASKSIN_PLUS_PLUS_MINOR 1
11 #define ASKSIN_PLUS_PLUS_SERVICE 7
12 
13 #define ASKSIN_PLUS_PLUS_VERSION (ASKSIN_PLUS_PLUS_MAJOR * 10000 \
14  + ASKSIN_PLUS_PLUS_MINOR * 100 + ASKSIN_PLUS_PLUS_SERVICE)
15 
16 #define STRINGIZE2(s) #s
17 #define STRINGIZE(s) STRINGIZE2(s)
18 #define ASKSIN_PLUS_PLUS_VERSION_STR STRINGIZE(ASKSIN_PLUS_PLUS_MAJOR) \
19  "." STRINGIZE(ASKSIN_PLUS_PLUS_MINOR) "." STRINGIZE(ASKSIN_PLUS_PLUS_SERVICE)
20 
21 #define ASKSIN_PLUS_PLUS_IDENTIFIER F("AskSin++ V" ASKSIN_PLUS_PLUS_VERSION_STR " (" __DATE__ " " __TIME__ ")")
22 
23 
24 #define CONFIG_FREQ1 0
25 #define CONFIG_FREQ2 1
26 #define CONFIG_BOOTSTATE 2 //location of current boot state for ResetOnBoot
27 
28 #include <Debug.h>
29 #include <stdint.h>
30 
31 #ifdef ARDUINO_ARCH_STM32F1
32  #define _delay_us(us) delayMicroseconds(us)
33  inline void _delay_ms(uint32_t ms) { do { delayMicroseconds(1000); } while( (--ms) > 0); }
34 
35  #define NOT_AN_INTERRUPT -1
36  #define digitalPinToInterrupt(pin) (pin)
37  #define enableInterrupt(pin,handler,mode) attachInterrupt(pin,handler,mode)
38  #define disableInterrupt(pin) detachInterrupt(pin)
39  #define memcmp_P(src,dst,count) memcmp((src),(dst),(count))
40 #else
41  typedef uint8_t uint8;
42  typedef uint16_t uint16;
43  // if we have no EnableInterrupt Library - and also no PCINT - use polling
44  #ifndef EnableInterrupt_h
45  #define enableInterrupt(pin,handler,mode) pinpolling##pin().enable(pin,handler,mode)
46  #define disableInterrupt(pin) pinpolling##pin().disable()
47  #endif
48 #endif
49 
50 
51 #include <Storage.h>
52 #include <Pins.h>
53 #include <Debug.h>
54 #include <Activity.h>
55 #include <Led.h>
56 #include <Buzzer.h>
57 #include <AlarmClock.h>
58 #include <Message.h>
59 #include <Button.h>
60 #include <Radio.h>
61 #include <BatterySensor.h>
62 
63 
64 namespace as {
65 
66 extern const char* __gb_chartable;
67 
71 class AskSinBase {
72  Storage storage;
73 public:
80  static void pgm_read(uint8_t* dest,uint16_t adr,uint8_t size) {
81  for( int i=0; i<size; ++i, ++dest ) {
82  *dest = pgm_read_byte(adr + i);
83  }
84  }
90  static uint8_t toChar (uint8_t c) {
91  return *(__gb_chartable+c);
92  }
99  static uint16_t crc16 (uint16_t crc,uint8_t d) {
100  crc ^= d;
101  for( uint8_t i = 8; i != 0; --i ) {
102  crc = (crc >> 1) ^ ((crc & 1) ? 0xA001 : 0 );
103  }
104  return crc;
105  }
106 
113  static uint32_t crc24(const uint8_t* data,int len) {
114  uint32_t crc = 0xB704CEL;
115  for( uint8_t i=0; i<len; ++i) {
116  crc = crc24(crc,data[i]);
117  }
118  return crc;
119  }
120 
127  static uint32_t crc24(uint32_t crc,uint8_t d) {
128  crc ^= ((uint32_t)d) << 16;
129  for( uint8_t i = 0; i < 8; i++) {
130  crc <<= 1;
131  if (crc & 0x1000000) {
132  crc ^= 0x1864CFBL;
133  }
134  }
135  return crc & 0xFFFFFFL;
136  }
137 
138  // get timer count in ticks
139  static uint32_t byteTimeCvt(uint8_t tTime) {
140  if( tTime == 0xff ) return 0xffffffff;
141  const uint16_t c[8] = {1,10,50,100,600,3000,6000,36000};
142  return decis2ticks( (uint32_t)(tTime & 0x1F) * c[tTime >> 5] );
143  }
144 
145  static uint32_t byteTimeCvtSeconds (uint8_t tTime) {
146  const uint8_t c[2] = {1,60};
147  return seconds2ticks( (uint32_t)(tTime & 0x7F) * c[tTime >> 7] );
148  }
149 
150  // get timer count in ticks
151  static uint32_t intTimeCvt(uint16_t iTime) {
152  if (iTime == 0x00) return 0x00;
153  if (iTime == 0xffff) return 0xffffffff;
154 
155  uint32_t tByte;
156  if ((iTime & 0x1F) != 0) {
157  tByte = 2;
158  for (uint8_t i = 1; i < (iTime & 0x1F); i++) tByte *= 2;
159  } else tByte = 1;
160 
161  return decis2ticks( (uint32_t)tByte*(iTime>>5) );
162  }
163 
169  static uint32_t nextSendSlot (const HMID& id,uint8_t msgcnt) {
170  uint32_t value = ((uint32_t)id) << 8 | msgcnt;
171  value = (value * 1103515245 + 12345) >> 16;
172  value = (value & 0xFF) + 480;
173  value *= 250;
174 
175  DDEC(value / 1000);DPRINT(".");DDECLN(value % 1000);
176 
177  return value;
178  }
186  static uint8_t readPin(uint8_t pinnr,uint8_t enablenr=0,uint8_t ms=0) {
187  uint8_t value=0;
188  pinMode(pinnr,INPUT_PULLUP);
189  if( enablenr != 0 ) {
190  digitalWrite(enablenr,HIGH);
191  if( ms != 0 ) {
192  _delay_ms(ms);
193  }
194  }
195  value = digitalRead(pinnr);
196  pinMode(pinnr,OUTPUT);
197  digitalWrite(pinnr,LOW);
198  if( enablenr != 0 ) {
199  digitalWrite(enablenr,LOW);
200  }
201  return value;
202  }
203 
204 };
205 
206 template <class StatusLed,class Battery,class Radio,class Buzzer=NoBuzzer>
207 class AskSin : public AskSinBase {
208 
209 public:
210  typedef StatusLed LedType;
211  typedef Battery BatteryType;
212  typedef Radio RadioType;
213  typedef Buzzer BuzzerType;
214 
215  LedType led;
216  BatteryType battery;
217  Activity activity;
218  RadioType radio;
219  BuzzerType buzzer;
220 
221  void init (const HMID& id) {
222  srand((unsigned int&)id);
223  led.init();
224  buzzer.init();
225  bool ccinitOK = radio.init();
226  radio.enable();
227  // start the system timer
228  sysclock.init();
229  // signal start to user
230  led.set(ccinitOK ? LedStates::welcome : LedStates::failure);
231  // delay first send by random time
232  radio.setSendTimeout((rand() % 3500)+1000);
233  }
234 
235  void initBattery(uint16_t interval,uint8_t low,uint8_t critical) {
236  battery.init(seconds2ticks(interval),sysclock);
237  battery.low(low);
238  battery.critical(critical);
239  }
240 
241  void config (const StorageConfig& sc) {
242  if( sc.valid() == true ) {
243  uint8_t f1 = sc.getByte(CONFIG_FREQ1);
244  uint8_t f2 = sc.getByte(CONFIG_FREQ2);
245  // check if CONFIG_FREQ1 is in range 0x60...0x6A -> 868,3MHz -550kHz/+567kHz
246  if( f1 >= 0x60 && f1 <= 0x6A ) {
247  DPRINT(F("Config Freq: 0x21"));DHEX(f1);DHEXLN(f2);
248  radio.initReg(CC1101_FREQ2, 0x21);
249  radio.initReg(CC1101_FREQ1, f1);
250  radio.initReg(CC1101_FREQ0, f2);
251  }
252  }
253  }
254 
255  bool runready () {
256  return sysclock.runready();
257  }
258 
259  // call by the device before the device sends a message
260  // can be used to update data by the device sketch
261  void prepareSend (__attribute__((unused)) Message& msg) {}
262 
263  // call after send a message to a peer
264  void sendPeer () {}
265 
266  // use radio timer to wait given millis
267  void waitTimeout(uint16_t millis) {
268  radio.waitTimeout(millis);
269  }
270 
271  void setIdle () {
272  radio.setIdle();
273  battery.setIdle();
274  }
275 
276  void unsetIdle () {
277  battery.unsetIdle();
278  }
279 
280  void wakeup () {
281  radio.wakeup();
282  }
283 
284 #if defined(ARDUINO_ARCH_AVR) && ! ( defined(ARDUINO_AVR_ATmega32) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega128__))
285  template <bool ENABLETIMER2=false, bool ENABLEADC=false>
286  void idle () { activity.savePower< Idle<ENABLETIMER2,ENABLEADC> >(*this); }
287 
288  template <bool ENABLETIMER2=false>
289  void sleep () { activity.savePower< Sleep<ENABLETIMER2> >(*this); }
290 
291  void sleepForever () { activity.sleepForever(*this); }
292 #endif
293 };
294 
295 #ifndef NORTC
296 template <class StatusLed,class Battery,class Radio,class Buzzer=NoBuzzer>
297 class AskSinRTC : public AskSin<StatusLed,Battery,Radio,Buzzer> {
298 public:
299  void init (const HMID& id) {
301  // init real time clock - 1 tick per second
302  rtc.init();
303  }
304 
305  void initBattery(uint16_t interval,uint8_t low,uint8_t critical) {
306  this->battery.init(interval,rtc);
307  this->battery.low(low);
308  this->battery.critical(critical);
309  }
310 
311 
312  bool runready () {
313  return rtc.runready() || AskSin<StatusLed,Battery,Radio,Buzzer>::runready();
314  }
315 
316 #if defined(ARDUINO_ARCH_AVR) && ! ( defined(ARDUINO_AVR_ATmega32) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega128__))
317  template <bool ENABLETIMER2=false>
318  void sleep () { this->activity.template savePower< SleepRTC >(*this); }
319 #endif
320 };
321 #endif
322 
323 }
324 
325 #endif
as::Activity
Definition: Activity.h:148
as::Sleep
Definition: Activity.h:49
as::Message
Definition: Message.h:51
as::AskSinBase::toChar
static uint8_t toChar(uint8_t c)
Definition: AskSinPP.h:90
as::AskSin
Definition: AskSinPP.h:207
as::AskSinBase::crc16
static uint16_t crc16(uint16_t crc, uint8_t d)
Definition: AskSinPP.h:99
as::StorageConfig
Definition: Storage.h:464
as::StatusLed
Definition: Led.h:132
as::Buzzer
Definition: Buzzer.h:16
as::AskSinRTC
Definition: AskSinPP.h:297
as::AskSinBase::crc24
static uint32_t crc24(uint32_t crc, uint8_t d)
Definition: AskSinPP.h:127
as::AskSinBase::readPin
static uint8_t readPin(uint8_t pinnr, uint8_t enablenr=0, uint8_t ms=0)
Definition: AskSinPP.h:186
as::AskSinBase::pgm_read
static void pgm_read(uint8_t *dest, uint16_t adr, uint8_t size)
Definition: AskSinPP.h:80
as::Radio
Definition: Radio.h:767
as::AskSinBase
Definition: AskSinPP.h:71
as::Storage
Definition: Storage.h:451
as::AskSinBase::crc24
static uint32_t crc24(const uint8_t *data, int len)
Definition: AskSinPP.h:113
as::AskSinBase::nextSendSlot
static uint32_t nextSendSlot(const HMID &id, uint8_t msgcnt)
Definition: AskSinPP.h:169
as::Idle
Definition: Activity.h:22
as::HMID
Definition: HMID.h:14