void os_radio (u1_t mode) { hal_disableIRQs(); switch (mode) { case RADIO_RST: // put radio to sleep opmode(OPMODE_SLEEP); break; case RADIO_TX: // transmit frame now starttx(); // buf=LMIC.frame, len=LMIC.dataLen break; case RADIO_RX: // receive frame now (exactly at rxtime) startrx(RXMODE_SINGLE); // buf=LMIC.frame, time=LMIC.rxtime, timeout=LMIC.rxsyms break; case RADIO_RXON: // start scanning for beacon now startrx(RXMODE_SCAN); // buf=LMIC.frame break; } hal_enableIRQs(); }
// get random seed from wideband noise rssi void radio_init () { hal_disableIRQs(); // manually reset radio #ifdef CFG_sx1276_radio hal_pin_rst(0); // drive RST pin low #else hal_pin_rst(1); // drive RST pin high #endif hal_waitUntil(os_getTime()+ms2osticks(1)); // wait >100us hal_pin_rst(2); // configure RST pin floating! hal_waitUntil(os_getTime()+ms2osticks(5)); // wait 5ms opmode(OPMODE_SLEEP); // some sanity checks, e.g., read version number u1_t v = readReg(RegVersion); #ifdef CFG_sx1276_radio ASSERT(v == 0x12 ); #elif CFG_sx1272_radio ASSERT(v == 0x22); #else #error Missing CFG_sx1272_radio/CFG_sx1276_radio #endif // seed 15-byte randomness via noise rssi rxlora(RXMODE_RSSI); while( (readReg(RegOpMode) & OPMODE_MASK) != OPMODE_RX ); // continuous rx for(int i=1; i<16; i++) { for(int j=0; j<8; j++) { u1_t b; // wait for two non-identical subsequent least-significant bits while( (b = readReg(LORARegRssiWideband) & 0x01) == (readReg(LORARegRssiWideband) & 0x01) ); randbuf[i] = (randbuf[i] << 1) | b; } } randbuf[0] = 16; // set initial index #ifdef CFG_sx1276mb1_board // chain calibration writeReg(RegPaConfig, 0); // Launch Rx chain calibration for LF band writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START); while((readReg(FSKRegImageCal)&RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING){ ; } // Sets a Frequency in HF band u4_t frf = 868000000; writeReg(RegFrfMsb, (u1_t)(frf>>16)); writeReg(RegFrfMid, (u1_t)(frf>> 8)); writeReg(RegFrfLsb, (u1_t)(frf>> 0)); // Launch Rx chain calibration for HF band writeReg(FSKRegImageCal, (readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_MASK)|RF_IMAGECAL_IMAGECAL_START); while((readReg(FSKRegImageCal) & RF_IMAGECAL_IMAGECAL_RUNNING) == RF_IMAGECAL_IMAGECAL_RUNNING) { ; } #endif /* CFG_sx1276mb1_board */ opmode(OPMODE_SLEEP); hal_enableIRQs(); }
// schedule immediately runnable job void os_setCallback (osjob_t* job, osjobcb_t cb) { osjob_t** pnext; hal_disableIRQs(); // remove if job was already queued os_clearCallback(job); // fill-in job job->func = cb; job->next = NULL; // add to end of run queue for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next)); *pnext = job; hal_enableIRQs(); }
// execute jobs from timer and from run queue once void os_runloop_once () { osjob_t* j = NULL; hal_disableIRQs(); // check for runnable jobs if(OS.runnablejobs) { j = OS.runnablejobs; OS.runnablejobs = j->next; } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs j = OS.scheduledjobs; OS.scheduledjobs = j->next; } else { // nothing pending hal_sleep(); // wake by irq (timer already restarted) } hal_enableIRQs(); if(j) { // run job callback j->func(j); } }
// schedule timed job void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) { osjob_t** pnext; hal_disableIRQs(); // remove if job was already queued os_clearCallback(job); // fill-in job job->deadline = time; job->func = cb; job->next = NULL; // insert into schedule for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) { if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!) // enqueue before next element and stop job->next = *pnext; break; } } *pnext = job; hal_enableIRQs(); }
// LMIC run loop, as a FreeRTOS task void os_runloop(void *pvParameters) { osjob_t *j = NULL; for(;;) { hal_disableIRQs(); // check for runnable jobs j = NULL; if(OS.runnablejobs) { j = OS.runnablejobs; OS.runnablejobs = j->next; } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs j = OS.scheduledjobs; OS.scheduledjobs = j->next; } hal_enableIRQs(); if (j) { // run job callback j->func(j); } else { //vTaskSuspend(NULL); } } }
u1_t radio_rssi () { hal_disableIRQs(); u1_t r = readReg(LORARegRssiValue); hal_enableIRQs(); return r; }
// clear scheduled job void os_clearCallback (osjob_t* job) { hal_disableIRQs(); unlinkjob(&OS.scheduledjobs, job); unlinkjob(&OS.runnablejobs, job); hal_enableIRQs(); }