OT_WEAK void dll_scan_timeout(void) { /// This function just operates the timing-out of the RX. RX is forced into /// timeout when there is no data being received OR if the MAC is operating /// under the Arbitrated regime, which uses strict time-slots. /// @note if you want to use a built-in RX termination or polling timer inside /// the radio core (some devices have these), be very careful. If the radio /// timer gets out of sync with the kernel (i.e. if your core timer isn't very /// accurate), then it is going to cause all sorts of timing glitches. Giving /// the kernel control over listening makes the system more stable and better /// synchronized. Usage of HW RX timer is mostly useful for very specific /// applications using very custom builds of OpenTag. #if (RF_FEATURE(RXTIMER) == DISABLED) // If not presently receiving, time-out the RX. // else if presently receiving, pad timeout by 128 if ((radio.state != RADIO_DataRX) || (dll.comm.csmaca_params & M2_CSMACA_A2P)) { ///@todo change to LISTEN rm2_rxtimeout_isr(); } else { sys.task[TASK_radio].event = 5; sys_task_setnext(&sys.task[TASK_radio], 128); } #else // Add a little bit of time in case the radio timer is a bit slow. sys_task_setnext(&sys.task[TASK_radio]->nextevent, 10); sys.task[TASK_radio].event = 0; #endif }
OT_WEAK void dll_systask_beacon(ot_task task) { /// The beacon rountine runs as an idependent systask. m2session* b_session; if ((task->event == 0) || (dll.netconf.b_attempts == 0)) { dll_idle(); return; } /// Load file-based beacon: /// Open BTS ISF Element and read the beacon sequence. Make sure there is /// a beacon file of non-zero length and that beacons are presently enabled. if (dll.netconf.dd_flags == 0) { ot_u16 scratch; vlFILE* fp; fp = ISF_open_su( ISF_ID(beacon_transmit_sequence) ); if (fp == NULL) { return; //goto dll_systask_beacon_STOP; } if (fp->length == 0) { vl_close(fp); return; //goto dll_systask_beacon_STOP; } // a little hack scratch = fp->start; fp->start += task->cursor; /// Beacon List Management: /// <LI> Move cursor onto next beacon period (above, +8)</LI> /// <LI> Loop cursor if it is past the length of the list </LI> /// <LI> In special case where cursor = 254, everything still works! </LI> task->cursor += 8; task->cursor = (task->cursor >= fp->length) ? 0 : task->cursor; // Load next beacon into btemp, then undo the start hack, then close vl_load(fp, 8, dll.netconf.btemp); fp->start = scratch; vl_close(fp); } // First 2 bytes: Chan ID, Cmd Code // - Setup beacon ad-hoc session, on specified channel (ad hoc sessions never return NULL) // - Assure cmd code is always Broadcast & Announcement b_session = session_new( &dll_beacon_applet, 0, dll.netconf.btemp[0], (M2_NETSTATE_INIT | M2_NETSTATE_REQTX | M2_NETFLAG_FIRSTRX) ); b_session->subnet = dll.netconf.b_subnet; b_session->extra = dll.netconf.btemp[1]; b_session->flags = dll.netconf.btemp[1] & 0x78; //b_session->flags |= (b_session->extra & 0x30); // Last 2 bytes: Next Scan ticks sys_task_setnext(task, TI2CLK( PLATFORM_ENDIAN16(*(ot_u16*)&dll.netconf.btemp[6]) )); ///@note this might not be necessary or wise! //return; //dll_systask_beacon_STOP: //dll_idle(); }
OT_WEAK void dll_systask_sleepscan(ot_task task) { /// The Sleep Scan process runs as an independent task. It is very similar /// to the Hold Scan process, which actually calls this same routine. They /// use independent task markers, however, so they behave differently. ot_u8 s_channel; ot_u8 s_code; ot_uni16 scratch; vlFILE* fp; m2session* s_new; /// event = 0 is the initializer, but there is no state-based operation /// or any heap-stored data for this task, so it does nothing if (task->event == 0) { return; } fp = ISF_open_su( task->event ); ///@note fp doesn't really need to be asserted unless you are mucking /// with things in test builds. /// Pull channel ID and Scan flags scratch.ushort = vl_read(fp, task->cursor); s_channel = scratch.ubyte[0]; s_code = scratch.ubyte[1]; /// Set the next idle event from the two-byte Next Scan field. /// The DASH7 registry is big-endian. scratch.ushort = PLATFORM_ENDIAN16( vl_read(fp, (task->cursor)+=2 ) ); sys_task_setnext(task, scratch.ushort); /// Advance cursor to next datum, go back to 0 if end of sequence /// (still works in special case where cursor = 254) task->cursor += 2; task->cursor = (task->cursor >= fp->length) ? 0 : task->cursor; vl_close(fp); /// Choosing Background-Scan or Foreground-Scan is based on scan-code. /// If b7 is set, do a Background-Scan. At the session level, the "Flood" /// select uses b6, which is why there is a >> 1. s_new = session_new(&dll_scan_applet, 0, s_channel, ((M2_NETSTATE_REQRX | M2_NETSTATE_INIT) | (s_code & 0x80) >> 1) ); s_new->extra = s_code; }
/** DLL Systask RF I/O routines <BR> * ========================================================================<BR> * These routines & subroutines are called from the dll_systack() function. * All of these routines interact with the Radio module & driver, which is an * interrupt-driven pre-emptive task. */ OT_WEAK void dll_init_rx(m2session* active) { /// RX initialization is called by the session activation routine, and it is /// often the result of an SSS or HSS invocation. Scanning allows a 1 tick /// latency for other tasks, although this could be potentially increased. /// Background scans are very fast, and pending tasks will not be impacted /// greatly by the strict latency requirement. Foreground scans can last for /// potentially long periods of time, however. The latency, here, affects the /// the request-response turnaround but not the radio RX process itself. /// /// @todo A more adaptive method for scanning is planned, in which the latency /// drops to 1 only after a sync word is detected. ot_sig2 callback; ot_u16 min_timeout; sys.task_RFA.event = 3; //sys.task_RFA.reserved = 10; //un-necessary, RFA is max priority sys.task_RFA.latency = (active->netstate & M2_NETSTATE_RESP) ? \ _RESPRX_LATENCY : _REQRX_LATENCY; min_timeout = rm2_rxtimeout_floor(active->channel); if (dll.comm.rx_timeout < min_timeout) { dll.comm.rx_timeout = min_timeout; } sys_task_setnext(&sys.task[TASK_radio], (ot_u16)dll.comm.rx_timeout); // E.g. lights a LED DLL_SIG_RFINIT(sys.task_RFA.event); //For synchronization test only //if ((active->netstate & M2_NETFLAG_BG) == 0) { // sample_t1 = systim_chronstamp(&sample_t0); // sample_t0 = 0; //} callback = (active->netstate & M2_NETFLAG_BG) ? \ &dll_rfevt_brx : &dll_rfevt_frx; rm2_rxinit(active->channel, active->netstate, callback); }
void ext_systask(ot_task task) { switch (task->event) { case 0: break; case 1: // break and deactivate task if switch is *not* being held-down if (PALFI_WAKE_PORT->DIN & BOARD_SW2_PIN) { sys_task_setevent(task, 0); break; } case 2: { // Add new DASH7 comm task to kernel, using most defaults. session_tmpl s_tmpl; sys_task_setevent(task, 1); sys_task_setnext(task, 512); s_tmpl.channel = 7; s_tmpl.subnetmask = 0; s_tmpl.flagmask = 0; m2task_immediate(&s_tmpl, &applet_adcpacket); } break; } }