Пример #1
0
OT_WEAK void rm2_init(void) {
    vlFILE* fp;
    
    /// Set universal Radio module initialization defaults
    radio.state     = RADIO_Idle;
    radio.evtdone   = &otutils_sig2_null;

    /// These Radio Link features are available on the SPIRIT1
    ///@todo see if this and the "Set startup channel" part of the init can
    ///      get bundled into a common initialization function in radio_task.c
#   if (OT_FEATURE(RF_LINKINFO))
#       if (M2_FEATURE(RSCODE))
#           define _CORRECTIONS RADIO_LINK_CORRECTIONS
#       else
#           define _CORRECTIONS 0
#       endif
    radio.link.flags        = _CORRECTIONS | RADIO_LINK_PQI | RADIO_LINK_SQI \
                            | RADIO_LINK_LQI | RADIO_LINK_AGC;
#   endif
    radio.link.offset_thr   = 0;
    radio.link.raw_thr      = 0;
    
    /// Set startup channel to an always invalid channel ID (0xF0), and run 
    /// lookup on the default channel (0x18) to kick things off.  Since the 
    /// startup channel will always be different than a real channel, the 
    /// necessary settings and calibration will always occur. 
    phymac[0].channel   = 0xF0;
    phymac[0].tx_eirp   = 0x7F;
    fp                  = ISF_open_su( ISF_ID(channel_configuration) );
    rm2_channel_lookup(0x18, fp);
    vl_close(fp);
}
Пример #2
0
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();
}
Пример #3
0
void AES_load_static_key(ot_u8 key_id, ot_u32* key) {
    ot_int i;
    vlFILE* fp;
    
    fp = ISF_open_su(key_id);
    for (i=0; i<16; i+=2) {
        *(ot_u16*)((ot_u8*)key+i) = vl_read(fp, i);
    }
    vl_close(fp);
}
Пример #4
0
OT_WEAK void dll_refresh(void) {
    ot_uni16 scratch;
    vlFILE* fp;

    /// Open Network Features ISF and load the values from that file into the
    /// cached dll.netconf settings.

    fp = ISF_open_su(0);
    vl_load(fp, 10, dll.netconf.vid);
    dll.netconf.dd_flags    = 0;
    dll.netconf.hold_limit  = PLATFORM_ENDIAN16(dll.netconf.hold_limit);
    vl_close(fp);

    fp = ISF_open_su(1);
    vl_load(fp, 8, dll.netconf.uid);
    vl_close(fp);

    // Reset the Scheduler (only does anything if scheduler is implemented)
    dll_refresh_rts();
    sub_dll_flush();
}
Пример #5
0
void sub_build_uhfmsg(ot_int* buffer) {
/// This is the routine that builds the DASH7 UDP generic protocol message.
/// The protocol has data elements marked by a letter (T, V, R, E, D) that
/// signify Temperature, Voltage, RSSI (LF), PaLFi wake Event, and RX Data.
/// The elements are fixed/known length.
    command_tmpl    c_tmpl;
    ot_u8*          data_start;
    ot_u8           status;

    // Broadcast request (takes no 2nd argument)
    otapi_open_request(ADDR_broadcast, NULL);

    // Insert Transport-Layer headers
    c_tmpl.type     = CMDTYPE_na2p_request;
    c_tmpl.opcode   = CMD_udp_on_file;
    c_tmpl.extension= CMDEXT_no_response;
    otapi_put_command_tmpl(&status, &c_tmpl);
    otapi_put_dialog_tmpl(&status, NULL);       // NULL = defaults

    // UDP Header
    q_writebyte(&txq, 255);        // Source Port: 255 (custom application port)
    q_writebyte(&txq, 255);        // Destination Port (same value)

    data_start = txq.putcursor;

    // Place temperature data
    q_writebyte(&txq, 'T');
    q_writeshort(&txq, buffer[0]);

    // Place Voltage data
    q_writebyte(&txq, 'V');
    q_writeshort(&txq, buffer[1]);

    // Place RSSI data
    q_writebyte(&txq, 'R');
    q_writeshort(&txq, radio.last_rssi);


    // Store this information into the Port 255 file for continuous, automated
    // reporting by DASH7/OpenTag until it is updated next time.  The length of
    // this information is always 6 bytes.
    {
        vlFILE* fp;
        fp = ISF_open_su(255);
        if (fp != NULL) {
            vl_store(fp, 6, data_start);
            vl_close(fp);
        }
    }

    // Finish Message
    otapi_close_request();
}
Пример #6
0
/** ALP Processor Callback for Starting a Ping <BR>
  * ========================================================================<BR>
  * "ALP" is the NDEF-based set of low-level API protocols that OpenTag uses.
  * ALP messages can come-in over any communication method: wire, wireless, 
  * telepathy... anything that can transfer a packet payload.
  *
  * Some ALPs are standardized. Those get handled by OTlib automatically.  ALPs
  * that are not recognized are sent to this function to be handled.  In this
  * demo, we are using a very simple ALP, shown below:
  *
  * ALP Payload Length:         0
  * ALP Protocol ID:            255 (FF)
  * ALP Protocol Commands:      0-127 (00-7F) corresponding to channel to sniff
  *
  * The "user_id" parameter corresponds to the Device ID that sent this ALP.
  * 
  * A quickstart guide to the ALP API is available on the Indigresso Wiki.
  * http://www.indigresso.com/wiki/doku.php?id=opentag:api:quickstart
  */ 
void otapi_alpext_proc(alp_tmpl* alp, id_tmpl* user_id) {
/// The function app_invoke() will cause the kernel to call ext_systask() as
/// soon as resources are available.
    vlFILE*     fp;
    ot_uni16    scratch;
    ot_u8       channel;
    ot_u8       retval;

    // Start the task only if: Caller is ROOT, ALP Call is Protocol-255, Task is idle
    if (    auth_isroot(user_id)    \
        &&  (alp->inrec.id == 0xFF) \
        &&  (APP_TASK.event == 0)   )   {
        
        /// Make sure channel is spec-legal.  If so, set the channel of the 
        /// first (and only) in the channel list to the specified one, and also
        /// set the channel of the hold scan accordingly.  By default, the scan
        /// is updated every second.  The next scan will have these settings.
        retval  = 0;
        channel = alp->inrec.cmd & 0x7F;
        if (((channel & 0xF0) <= 0x20) && ((channel & 0x0F) <= 0x0E)) {
            fp                  = ISF_open_su(ISF_ID(channel_configuration));
            scratch.ushort      = vl_read(fp, 0);
            scratch.ubyte[0]    = channel;
            vl_write(fp, 0, scratch.ushort);
            vl_close(fp);
            
            fp                  = ISF_open_su(ISF_ID(hold_scan_sequence));
            scratch.ushort      = vl_read(fp, 0);
            scratch.ubyte[0]    = channel;
            vl_write(fp, 0, scratch.ushort);
            vl_close(fp);
            
            retval = 1; //success
        }
        
        alp_load_retval(alp, retval);
    }
}
Пример #7
0
OT_WEAK void dll_change_settings(ot_u16 new_mask, ot_u16 new_settings) {
    vlFILE* fp_active;
    vlFILE* fp_supported;

    // Get Active Settings, Get Supported Settings,
    // Mask-out unsupported settings, apply to new active settings
    ///@todo assert fp
    fp_active           = ISF_open_su( 0x00 );
    fp_supported        = ISF_open_su( 0x01 );
    new_mask           &= vl_read(fp_supported, 8);
    dll.netconf.active  = vl_read(fp_active, 4);
    new_settings       &= new_mask;
    dll.netconf.active &= ~new_mask;
    dll.netconf.active |= new_settings;

    // Write the new settings to the ISF 0
    vl_write(fp_active, 4, dll.netconf.active);
    vl_close(fp_active);
    vl_close(fp_supported);

    // Flush the System of all Sessions and Events, and restart it
    sub_dll_flush();
}
Пример #8
0
void m2np_put_deviceid(ot_bool use_vid) {
    vlFILE* fp;
    
    //file 0=network_settings, 1=device_features
    fp = ISF_open_su( (ot_u8)(use_vid == False) );
    ///@todo assert fp

    q_writeshort_be( &txq, vl_read(fp, 0) );
    if (use_vid == False) {
    	q_writeshort_be( &txq, vl_read(fp, 2) );
    	q_writeshort_be( &txq, vl_read(fp, 4) );
    	q_writeshort_be( &txq, vl_read(fp, 6) );
    }
    
    vl_close(fp);
}
Пример #9
0
ot_bool m2np_idcmp(ot_int length, void* id) {
    ot_bool check   = True;
    ot_u8   use_uid = (length == 8);
    vlFILE* fp;
    
    //file 0=network_settings, 1=device_features
    fp      = ISF_open_su( use_uid );
    check  &= ( ((ot_u16*)id)[0] == vl_read(fp, 0));

    if (use_uid) {
        check &= ( ((ot_u16*)id)[1] == vl_read(fp, 2) );
        check &= ( ((ot_u16*)id)[2] == vl_read(fp, 4) );
        check &= ( ((ot_u16*)id)[3] == vl_read(fp, 6) );
    }
    
    vl_close(fp);
    return check;
}
Пример #10
0
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;
}
Пример #11
0
OT_WEAK void dll_refresh_rts(void) {
#if (OT_FEATURE(CRON) && M2_FEATURE(RTC_SCHEDULER))
///@todo need to update this implementation to also delete the old tasks.

    vlFILE* fp;

    // Early exit if RTS is not active
    if (dll.netconf.active_settings & M2_SET_SCHEDMASK) == 0)
        return;

    // - open the real-time-schedule ISF
    // - make sure the file is there
    // - make sure the file has at least 12 bytes (this is how much DLL uses)
    fp = ISF_open_su(ISF_ID_real_time_scheduler);
    if (fp != NULL) {
        if (fp->length < 12) {
            static const ot_task task_fn[3] = { &dll_systask_holdscan,
                                                &dll_systask_sleepscan,
                                                &dll_systask_beacon };

            ot_u16  sched_enable    = dll.netconf.active_settings & M2_SET_SCHEDMASK;
            ot_u16  cursor          = 0;
            ot_sigv* fn             = task_fn;

            // Apply Hold, Sleep, and Beacon RTS as specified in enabler bitmask
            while (sched_enable != 0) {
                if (sched_enable & M2_SET_HOLDSCHED) {
                    ot_u32 time_evt;
                    ot_u32 time_mask;
                    time_evt    = vl_read(fp, cursor);
                    time_mask   = 0xFFFF0000 | vl_read(fp, cursor+2);
                    otcron_add(*fn, CRONTIME_absolute, time_evt, time_mask);
                }
                fn++;
                cursor         += 4;
                sched_enable  <<= 1;
            }
        }
        vl_close(fp);
    }
#endif
}
Пример #12
0
void sub_build_uhfmsg(ot_int* buffer) {
/// This is the routine that builds the DASH7 UDP generic protocol message.
/// The protocol has data elements marked by a letter (T, V, R, E, D) that
/// signify Temperature, Voltage, RSSI (LF), PaLFi wake Event, and RX Data.
/// The elements are fixed/known length.
    session_tmpl    s_tmpl;
    command_tmpl    c_tmpl;
    ot_u8*          data_start;
    ot_u8           status;

    // Create a new session: you could change these parameters
    // Use "CHAN1" for odd events, "CHAN2" for even events
    s_tmpl.channel      = (palfi.wake_event & 1) ? ALERT_CHAN1 : ALERT_CHAN2;     
    s_tmpl.subnetmask   = 0;        // Use default subnet
    s_tmpl.flagmask     = 0;        // Use default app-flags
    s_tmpl.timeout      = 10;       // Do CSMA for no more than 10 ticks (~10 ms)
    otapi_new_session(&s_tmpl);
    
    // Broadcast request (takes no 2nd argument)
    otapi_open_request(ADDR_broadcast, NULL);
    
    // Insert Transport-Layer headers
    c_tmpl.type     = CMDTYPE_na2p_request;
    c_tmpl.opcode   = CMD_udp_on_file;
    c_tmpl.extension= CMDEXT_no_response;
    otapi_put_command_tmpl(&status, &c_tmpl);
    otapi_put_dialog_tmpl(&status, NULL);       // NULL = defaults
    
    // UDP Header
    q_writebyte(&txq, 255);        // Source Port: 255 (custom application port)
    q_writebyte(&txq, 255);        // Destination Port (same value)
    
    data_start = txq.putcursor;
    
    // Place temperature data
    q_writebyte(&txq, 'T');
    q_writeshort(&txq, buffer[0]);
    
    // Place Voltage data
    q_writebyte(&txq, 'V');
    q_writeshort(&txq, buffer[1]);
    
    // Place RSSI data
    q_writebyte(&txq, 'R');
    q_writestring(&txq, (ot_u8*)&palfi.rssi1, 3);

    // Place Action data
    q_writebyte(&txq, 'E');
    q_writebyte(&txq, (ot_int)palfi.wake_event);
    
    // Dump some received data
    if (palfi.wake_event) {
        q_writebyte(&txq, 'D');
        q_writestring(&txq, palfi.rxdata, 8);
    }
    
    // Store this information into the Port 255 file for continuous, automated
    // reporting by DASH7/OpenTag until it is updated next time.  The length of 
    // this information is always 23 bytes.
    {
    	vlFILE* fp;
    	fp = ISF_open_su(255);
    	if (fp != NULL) {
    		vl_store(fp, 23, data_start);
    		vl_close(fp);
    	}
    }
    
    // Finish Message
    otapi_close_request();
}