-
Notifications
You must be signed in to change notification settings - Fork 8
ISense application development
Before you begin to develop your own application the following points may be a matter of particular interest, but please note that the following annotations are explained in the iSense api documentation in detailed fashion. So have it look at it for further information.
- Your application must inherit from Application. Then its boot-method is called after power on, so you can influence the following behaviour of the system by registering tasks or timeouts which are called later on by the Os.
- The timeout-method is always called in the interrupt context, so be quick in there.
- Timeouts can be removed.
- Tasks are organized in a fifo-queue and executed all the time. If the queue is empty the device goes to sleep mode, if sleeping is allowed.
- Tasks can not be removed.
To transmit packets, you must use the current instance iSense::Radio class. This can be obtained from the isense::Os. The send-method of the isense::Radio requires the destination address, the length of the buffer to be transmitted, the buffer, options and a sender. For instance, a typical application would could look like this:
os_.radio().send(ISENSE_RADIO_BROADCAST_ADDR, len, outbuffer, Radio::ISENSE_RADIO_HEADER_OPTION_NONE, this );
The destination address is a 16-bit value indicating the intended receiver of the packet. If you specify ISENSE_RADIO_BROADCAST_ADDR, this packet is received by any other device in the broadcasting range.
Amongst others, the options tell the radio to perform and acknowledged or unacknowledged transmission. To use the default options, specify Radio::ISENSE_RADIO_HEADER_OPTION_NONE.
The sender parameter may be NULL or point to a class implementing the isense::Receiver interface. If this parameter is not NULL, the radio will notify the sender about success or failure. If you send without requesting an ack, the confirm-method of a Sender is called in the interrupt context as soon as the packet has been send by the radio. If you have requested an ack, it is called as soon as the acknowledgement arrived or after n failed tries.
To receive packets, the class that should receive packets must implement the isense::Receiver interface. It can be found in isense/radio.h and looks as follows:
class Receiver :
public iSenseObject
{
public:
virtual ~Receiver(){}
//----------------------------------------------------------------------------
/** This function is called by the radio where the Receiver is registered when
* a packet is received.
* \param len length of the packet to enqueue
* \param buf pointer to the payload of the packet (payload is copied)
* \param src_addr sender address of the packet
* \param dest_addr destination address of the packet
* \param lqi link quality indication for the packet
* \param sequence_no link layer single hop sequence number
* \param interface id of the interface that received the packet
*/
virtual void receive (uint8 len, const uint8 * buf, uint16 src_addr, uint16 dest_addr, uint16 lqi, uint8 sequence_no, uint8 interface) = 0;
};
Hence, first of all each class that wants to receive data must implement the receive method. It is called whenever a packet is received. It is passed the payload length, the buffer with the payload, source and destination address, and, besides other information, the id of the interface that received the packet.
As a convention, the first byte of the payload must contain the packet type information. By comparing this byte with the type you are interested in, you can determine whether this packet is targeted at this receiver. (As a result, you must place this type information in the first byte when sending). Applications should use packet types between 128 and 255, as types between 0 and 127 are reserved to iSense protocols. for an overview of the iSense packet types currently used, refer to the Radio::packet_types enum in isense/radio.h
By evaluating the interface information, you can find out where the payload came from. Inferface ids less than 128 represent hardware interfaces (currently only "0 = primary radio interface" is used), whiles interface ids greater than 127 represent software interfaces (currently only "0xFE = routing protocol" is used).
Second, you must register this receiver with the isense::Dispatcher in order to actually receive packets. This could be done in the application's boot-method:
os_.dispatcher().register_receiver(this);
A normal receiver obtains packets addressed to its own mac-address and the broadcast-address. Its receive-method is called in the normal context by processing the task-queue. A receiver must filter for its expected packets itself, e.g., by dropping packets for the broadcast address.
Another option is to register a a so-called fast receiver. A fast receiver obtains the same packets, but is called in the interrupt context. There can only be one fast receiver. To register as a fast receiver, do the following:
os_.dispatcher().register_fast_receiver(this);
A promisciuous_receiver obtains all packets the device hears, even though the destination address differs from the own one.
os_.dispatcher().register_promiscuous_receiver(this);
- Moreover an application can inherit from SleepHandler. If it registers itsself at the Os, it will be called before going to sleep and after wakeup. Be quick both methods standby and wakeup, because otherwise the internal time or wakeup times may get wrong.
- From the Os you get references to all system components like gpio, i2c, uart and adc.