Testing getting PJON working on mbed https://github.com/gioblu/PJON

Dependencies:   mbed

Committer:
earlz
Date:
Sat Jan 16 15:51:23 2016 +0000
Revision:
2:5648483c5dbc
Parent:
1:bd0ee507dd4c
Attempting to make things work, but it currently just freezes for some reason

Who changed what in which revision?

UserRevisionLine numberNew contents of line
earlz 0:fa2f348efd7e 1
earlz 0:fa2f348efd7e 2 /*-O//\ __ __
earlz 0:fa2f348efd7e 3 |-gfo\ |__| | | | |\ |
earlz 0:fa2f348efd7e 4 |!y°o:\ | __| |__| | \| v1.0
earlz 0:fa2f348efd7e 5 |y"s§+`\ Giovanni Blu Mitolo 2012 - 2015
earlz 0:fa2f348efd7e 6 /so+:-..`\ gioscarab@gmail.com
earlz 0:fa2f348efd7e 7 |+/:ngr-*.`\
earlz 0:fa2f348efd7e 8 |5/:%&-a3f.:;\ PJON is a device communications bus system that connects up to 255
earlz 0:fa2f348efd7e 9 \+//u/+g%{osv,,\ arduino boards over one wire up to 5.29kB/s data communication speed.
earlz 0:fa2f348efd7e 10 \=+&/osw+olds.\\ Contains acknowledge, collision detection, CRC and encpryption all done
earlz 0:fa2f348efd7e 11 \:/+-.-°-:+oss\ with micros() and delayMicroseconds(), with no use of interrupts or timers.
earlz 0:fa2f348efd7e 12 | | \oy\\ Pull down resistor on the bus is generally used to reduce interference.
earlz 0:fa2f348efd7e 13 > <
earlz 0:fa2f348efd7e 14 -| |-
earlz 0:fa2f348efd7e 15
earlz 0:fa2f348efd7e 16 Copyright (c) 2012-2015, Giovanni Blu Mitolo All rights reserved.
earlz 0:fa2f348efd7e 17
earlz 0:fa2f348efd7e 18 Redistribution and use in source and binary forms, with or without
earlz 0:fa2f348efd7e 19 modification, are permitted provided that the following conditions are met:
earlz 0:fa2f348efd7e 20 - Redistributions of source code must retain the above copyright
earlz 0:fa2f348efd7e 21 notice, this list of conditions and the following disclaimer.
earlz 0:fa2f348efd7e 22
earlz 0:fa2f348efd7e 23 - Redistributions in binary form must reproduce the above copyright
earlz 0:fa2f348efd7e 24 notice, this list of conditions and the following disclaimer in the
earlz 0:fa2f348efd7e 25 documentation and/or other materials provided with the distribution.
earlz 0:fa2f348efd7e 26
earlz 0:fa2f348efd7e 27 - All advertising materials mentioning features or use of this software
earlz 0:fa2f348efd7e 28 must display the following acknowledgement:
earlz 0:fa2f348efd7e 29 This product includes PJON software developed by Giovanni Blu Mitolo.
earlz 0:fa2f348efd7e 30
earlz 0:fa2f348efd7e 31 - Neither the name of PJON, PJON_ASK nor the
earlz 0:fa2f348efd7e 32 names of its contributors may be used to endorse or promote products
earlz 0:fa2f348efd7e 33 derived from this software without specific prior written permission.
earlz 0:fa2f348efd7e 34
earlz 0:fa2f348efd7e 35 This software is provided by the copyright holders and contributors"as is"
earlz 0:fa2f348efd7e 36 and any express or implied warranties, including, but not limited to, the
earlz 0:fa2f348efd7e 37 implied warranties of merchantability and fitness for a particular purpose
earlz 0:fa2f348efd7e 38 are disclaimed. In no event shall the copyright holder or contributors be
earlz 0:fa2f348efd7e 39 liable for any direct, indirect, incidental, special, exemplary, or consequential
earlz 0:fa2f348efd7e 40 damages (including, but not limited to, procurement of substitute goods or services;
earlz 0:fa2f348efd7e 41 loss of use, data, or profits; or business interruption) however caused and on any
earlz 0:fa2f348efd7e 42 theory of liability, whether in contract, strict liability, or tort (including
earlz 0:fa2f348efd7e 43 negligence or otherwise) arising in any way out of the use of this software, even if
earlz 0:fa2f348efd7e 44 advised of the possibility of such damage. */
earlz 0:fa2f348efd7e 45
earlz 0:fa2f348efd7e 46 #include "pjon.h"
earlz 0:fa2f348efd7e 47
earlz 0:fa2f348efd7e 48 /* Initiate PJON passing pin number:
earlz 0:fa2f348efd7e 49 Device's id has to be set through set_id()
earlz 0:fa2f348efd7e 50 before transmitting on the PJON network. */
earlz 0:fa2f348efd7e 51
earlz 0:fa2f348efd7e 52 PJON::PJON(PinName input_pin) : _input_pin(input_pin){
earlz 0:fa2f348efd7e 53 //_input_pin = DigitalInOut(input_pin);
earlz 0:fa2f348efd7e 54 this->initialize();
earlz 0:fa2f348efd7e 55 }
earlz 0:fa2f348efd7e 56
earlz 0:fa2f348efd7e 57
earlz 0:fa2f348efd7e 58 /* Initiate PJON passing pin number and the device's id: */
earlz 0:fa2f348efd7e 59
earlz 0:fa2f348efd7e 60 PJON::PJON(PinName input_pin, uint8_t device_id) : _input_pin(input_pin) {
earlz 0:fa2f348efd7e 61 _device_id = device_id;
earlz 0:fa2f348efd7e 62 this->initialize();
earlz 0:fa2f348efd7e 63 }
earlz 0:fa2f348efd7e 64
earlz 0:fa2f348efd7e 65
earlz 0:fa2f348efd7e 66 /* Initialization tasks: */
earlz 0:fa2f348efd7e 67
earlz 0:fa2f348efd7e 68 void PJON::initialize() {
earlz 0:fa2f348efd7e 69 this->set_error(dummy_error_handler);
earlz 0:fa2f348efd7e 70 _reg_timer.start();
earlz 0:fa2f348efd7e 71 for(int i = 0; i < MAX_PACKETS; i++) {
earlz 0:fa2f348efd7e 72 packets[i].state = NULL;
earlz 0:fa2f348efd7e 73 packets[i].timing = 0;
earlz 0:fa2f348efd7e 74 packets[i].attempts = 0;
earlz 0:fa2f348efd7e 75 }
earlz 0:fa2f348efd7e 76 }
earlz 0:fa2f348efd7e 77
earlz 0:fa2f348efd7e 78
earlz 0:fa2f348efd7e 79 /* Set the device id, passing a single byte (watch out to id collision) */
earlz 0:fa2f348efd7e 80
earlz 0:fa2f348efd7e 81 void PJON::set_id(uint8_t id) {
earlz 0:fa2f348efd7e 82 _device_id = id;
earlz 0:fa2f348efd7e 83 }
earlz 0:fa2f348efd7e 84
earlz 0:fa2f348efd7e 85
earlz 0:fa2f348efd7e 86 /* Pass as a parameter a void function you previously defined in your code.
earlz 0:fa2f348efd7e 87 This will be called when a correct message will be received.
earlz 0:fa2f348efd7e 88 Inside there you can code how to react when data is received.
earlz 0:fa2f348efd7e 89
earlz 0:fa2f348efd7e 90 void receiver_function(uint8_t length, uint8_t *payload) {
earlz 0:fa2f348efd7e 91 for(int i = 0; i < length; i++)
earlz 0:fa2f348efd7e 92 Serial.print((char)payload[i]);
earlz 0:fa2f348efd7e 93
earlz 0:fa2f348efd7e 94 Serial.print(" ");
earlz 0:fa2f348efd7e 95 Serial.println(length);
earlz 0:fa2f348efd7e 96 };
earlz 0:fa2f348efd7e 97
earlz 0:fa2f348efd7e 98 network.set_receiver(receiver_function); */
earlz 0:fa2f348efd7e 99
earlz 0:fa2f348efd7e 100 void PJON::set_receiver(receiver r) {
earlz 0:fa2f348efd7e 101 _receiver = r;
earlz 0:fa2f348efd7e 102 }
earlz 0:fa2f348efd7e 103
earlz 0:fa2f348efd7e 104
earlz 0:fa2f348efd7e 105 /* Pass as a parameter a void function you previously defined in your code.
earlz 0:fa2f348efd7e 106 This will be called when an error in communication occurs
earlz 0:fa2f348efd7e 107
earlz 0:fa2f348efd7e 108 void error_handler(uint8_t code, uint8_t data) {
earlz 0:fa2f348efd7e 109 Serial.print(code);
earlz 0:fa2f348efd7e 110 Serial.print(" ");
earlz 0:fa2f348efd7e 111 Serial.println(data);
earlz 0:fa2f348efd7e 112 };
earlz 0:fa2f348efd7e 113
earlz 0:fa2f348efd7e 114 network.set_error(error_handler); */
earlz 0:fa2f348efd7e 115
earlz 0:fa2f348efd7e 116 void PJON::set_error(pjon_error e) {
earlz 0:fa2f348efd7e 117 _error = e;
earlz 0:fa2f348efd7e 118 }
earlz 0:fa2f348efd7e 119
earlz 0:fa2f348efd7e 120
earlz 0:fa2f348efd7e 121 /* Check if the channel is free for transmission:
earlz 0:fa2f348efd7e 122 If an entire byte received contains no 1s it means
earlz 0:fa2f348efd7e 123 that there is no active transmission */
earlz 0:fa2f348efd7e 124
earlz 0:fa2f348efd7e 125 bool PJON::can_start() {
earlz 0:fa2f348efd7e 126 _input_pin.input(); //pinMode(_input_pin, INPUT);
earlz 0:fa2f348efd7e 127 this->send_bit(0, 2);
earlz 0:fa2f348efd7e 128 if(!this->read_byte())
earlz 0:fa2f348efd7e 129 return true;
earlz 0:fa2f348efd7e 130
earlz 0:fa2f348efd7e 131 return false;
earlz 0:fa2f348efd7e 132 }
earlz 0:fa2f348efd7e 133
earlz 0:fa2f348efd7e 134
earlz 0:fa2f348efd7e 135 /* Send a bit to the pin:
earlz 0:fa2f348efd7e 136 digitalWriteFast is used instead of standard digitalWrite
earlz 0:fa2f348efd7e 137 function to optimize transmission time */
earlz 0:fa2f348efd7e 138
earlz 0:fa2f348efd7e 139 void PJON::send_bit(uint8_t VALUE, int duration) {
earlz 1:bd0ee507dd4c 140 _input_pin = VALUE > 0; //digitalWrite(_input_pin, VALUE);
earlz 0:fa2f348efd7e 141 wait_us(duration);
earlz 0:fa2f348efd7e 142 }
earlz 0:fa2f348efd7e 143
earlz 0:fa2f348efd7e 144
earlz 0:fa2f348efd7e 145 /* Every byte is prepended with 2 synchronization padding bits. The first
earlz 0:fa2f348efd7e 146 is a longer than standard logic 1 followed by a standard logic 0.
earlz 0:fa2f348efd7e 147 __________ ___________________________
earlz 0:fa2f348efd7e 148 | SyncPad | Byte |
earlz 0:fa2f348efd7e 149 |______ |___ ___ _____ |
earlz 0:fa2f348efd7e 150 | | | | | | | | | |
earlz 0:fa2f348efd7e 151 | | 1 | 0 | 1 | 0 0 | 1 | 0 | 1 1 | 0 |
earlz 0:fa2f348efd7e 152 |_|____|___|___|_____|___|___|_____|___|
earlz 0:fa2f348efd7e 153 |
earlz 0:fa2f348efd7e 154 ACCEPTANCE
earlz 0:fa2f348efd7e 155
earlz 0:fa2f348efd7e 156 The reception tecnique is based on finding a logic 1 as long as the
earlz 0:fa2f348efd7e 157 first padding bit within a certain threshold, synchronizing to its
earlz 0:fa2f348efd7e 158 falling edge and checking if it is followed by a logic 0. If this
earlz 0:fa2f348efd7e 159 pattern is recognised, reception starts, if not, interference,
earlz 0:fa2f348efd7e 160 synchronization loss or simply absence of communication is
earlz 0:fa2f348efd7e 161 detected at byte level. */
earlz 0:fa2f348efd7e 162
earlz 0:fa2f348efd7e 163 void PJON::send_byte(uint8_t b) {
earlz 0:fa2f348efd7e 164 _input_pin = 1; //digitalWriteFast(_input_pin, HIGH);
earlz 0:fa2f348efd7e 165 wait_us(BIT_SPACER);
earlz 0:fa2f348efd7e 166 _input_pin = 0; //digitalWriteFast(_input_pin, LOW);
earlz 0:fa2f348efd7e 167 wait_us(BIT_WIDTH);
earlz 0:fa2f348efd7e 168
earlz 0:fa2f348efd7e 169 for(uint8_t mask = 0x01; mask; mask <<= 1) {
earlz 1:bd0ee507dd4c 170 _input_pin = (b & mask) > 0; //digitalWriteFast(_input_pin, b & mask);
earlz 0:fa2f348efd7e 171 wait_us(BIT_WIDTH);
earlz 0:fa2f348efd7e 172 }
earlz 0:fa2f348efd7e 173 }
earlz 0:fa2f348efd7e 174
earlz 0:fa2f348efd7e 175
earlz 0:fa2f348efd7e 176 /* An Example of how the string "@" is formatted and sent:
earlz 0:fa2f348efd7e 177
earlz 0:fa2f348efd7e 178 ID 12 LENGTH 4 CONTENT 64 CRC 130
earlz 0:fa2f348efd7e 179 ________________ ________________ ________________ __________________
earlz 0:fa2f348efd7e 180 |Sync | Byte |Sync | Byte |Sync | Byte |Sync | Byte |
earlz 0:fa2f348efd7e 181 |___ | __ |___ | _ |___ | _ |___ | _ _ |
earlz 0:fa2f348efd7e 182 | | | | | | | | | | | | | | | | | | | | | | |
earlz 0:fa2f348efd7e 183 | 1 |0|0000|11|00| 1 |0|00000|1|00| 1 |0|0|1|000000| 1 |0|0|1|0000|1|0|
earlz 0:fa2f348efd7e 184 |___|_|____|__|__|___|_|_____|_|__|___|_|_|_|______|___|_|_|_|____|_|_|
earlz 0:fa2f348efd7e 185
earlz 0:fa2f348efd7e 186 A standard packet transmission is a bidirectional communication between
earlz 0:fa2f348efd7e 187 two devices that can be divided in 3 different phases:
earlz 0:fa2f348efd7e 188
earlz 0:fa2f348efd7e 189 Channel analysis Transmission Response
earlz 0:fa2f348efd7e 190 _____ _____________________________ _____
earlz 0:fa2f348efd7e 191 | C-A | | ID | LENGTH | CONTENT | CRC | | ACK |
earlz 0:fa2f348efd7e 192 <--|-----|---------|----|--------|---------|-----|--> <----|-----|
earlz 0:fa2f348efd7e 193 | 0 | | 12 | 4 | 64 | 130 | | 6 |
earlz 0:fa2f348efd7e 194 |_____| |____|________|_________|_____| |_____| */
earlz 0:fa2f348efd7e 195
earlz 0:fa2f348efd7e 196 int PJON::send_string(uint8_t id, char *string, uint8_t length) {
earlz 0:fa2f348efd7e 197 if (!*string) return FAIL;
earlz 0:fa2f348efd7e 198
earlz 0:fa2f348efd7e 199 if(!this->can_start()) return BUSY;
earlz 0:fa2f348efd7e 200
earlz 0:fa2f348efd7e 201 uint8_t CRC = 0;
earlz 0:fa2f348efd7e 202 _input_pin.output(); //pinModeFast(_input_pin, OUTPUT);
earlz 0:fa2f348efd7e 203
earlz 0:fa2f348efd7e 204 this->send_byte(id);
earlz 0:fa2f348efd7e 205 CRC ^= id;
earlz 0:fa2f348efd7e 206 this->send_byte(length + 3);
earlz 0:fa2f348efd7e 207 CRC ^= length + 3;
earlz 0:fa2f348efd7e 208
earlz 0:fa2f348efd7e 209 for(uint8_t i = 0; i < length; i++) {
earlz 0:fa2f348efd7e 210 this->send_byte(string[i]);
earlz 0:fa2f348efd7e 211 CRC ^= string[i];
earlz 0:fa2f348efd7e 212 }
earlz 0:fa2f348efd7e 213
earlz 0:fa2f348efd7e 214 this->send_byte(CRC);
earlz 0:fa2f348efd7e 215 _input_pin = 0; //digitalWriteFast(_input_pin, LOW);
earlz 0:fa2f348efd7e 216
earlz 0:fa2f348efd7e 217 if(id == BROADCAST) return ACK;
earlz 0:fa2f348efd7e 218 Timer t;
earlz 0:fa2f348efd7e 219 t.start();
earlz 0:fa2f348efd7e 220 //unsigned long time = micros();
earlz 0:fa2f348efd7e 221 int response = FAIL;
earlz 0:fa2f348efd7e 222
earlz 0:fa2f348efd7e 223 /* Receive byte for an initial BIT_SPACER bit + standard bit total duration.
earlz 0:fa2f348efd7e 224 (freak condition used to avoid micros() overflow bug) */
earlz 2:5648483c5dbc 225 int time = 0;
earlz 2:5648483c5dbc 226 while(response == FAIL && !(t.read_us() >= BIT_SPACER + BIT_WIDTH)){
earlz 0:fa2f348efd7e 227 response = this->receive_byte();
earlz 2:5648483c5dbc 228 if(t.read_us() >= 101 && t.read_us() <= time){
earlz 2:5648483c5dbc 229 DigitalOut myled2(LED4);
earlz 2:5648483c5dbc 230 myled2 = 1;
earlz 2:5648483c5dbc 231 }
earlz 2:5648483c5dbc 232 time = t.read_us();
earlz 2:5648483c5dbc 233 }
earlz 0:fa2f348efd7e 234
earlz 0:fa2f348efd7e 235 t.stop();
earlz 2:5648483c5dbc 236 if (response == ACK || response == NAK) {
earlz 2:5648483c5dbc 237 DigitalOut myled(LED2);
earlz 2:5648483c5dbc 238 myled = 1;
earlz 2:5648483c5dbc 239 return response;
earlz 2:5648483c5dbc 240 }
earlz 0:fa2f348efd7e 241
earlz 0:fa2f348efd7e 242 return FAIL;
earlz 0:fa2f348efd7e 243 };
earlz 0:fa2f348efd7e 244
earlz 0:fa2f348efd7e 245
earlz 0:fa2f348efd7e 246 /* Insert a packet in the send list:
earlz 0:fa2f348efd7e 247 The added packet will be sent in the next update() call.
earlz 0:fa2f348efd7e 248 Using the timing parameter you can set the delay between every
earlz 0:fa2f348efd7e 249 transmission cyclically sending the packet (use remove() function stop it)
earlz 0:fa2f348efd7e 250
earlz 0:fa2f348efd7e 251 int hi = network.send(99, "HI!", 3, 1000000); // Send hi every second
earlz 0:fa2f348efd7e 252 _________________________________________________________________________
earlz 0:fa2f348efd7e 253 | | | | | | | |
earlz 0:fa2f348efd7e 254 | device_id | length | content | state | attempts | timing | registration |
earlz 0:fa2f348efd7e 255 |___________|________|_________|_______|__________|________|______________| */
earlz 0:fa2f348efd7e 256
earlz 0:fa2f348efd7e 257 int PJON::send(uint8_t id, char *packet, uint8_t length, unsigned long timing) {
earlz 0:fa2f348efd7e 258
earlz 0:fa2f348efd7e 259 char *str = (char *) malloc(length);
earlz 0:fa2f348efd7e 260
earlz 0:fa2f348efd7e 261 if(str == NULL) {
earlz 0:fa2f348efd7e 262 this->_error(MEMORY_FULL, FAIL);
earlz 0:fa2f348efd7e 263 return FAIL;
earlz 0:fa2f348efd7e 264 }
earlz 0:fa2f348efd7e 265
earlz 0:fa2f348efd7e 266 memcpy(str, packet, length);
earlz 0:fa2f348efd7e 267
earlz 0:fa2f348efd7e 268 for(uint8_t i = 0; i < MAX_PACKETS; i++)
earlz 0:fa2f348efd7e 269 if(packets[i].state == NULL) {
earlz 0:fa2f348efd7e 270 packets[i].content = str;
earlz 0:fa2f348efd7e 271 packets[i].device_id = id;
earlz 0:fa2f348efd7e 272 packets[i].length = length;
earlz 0:fa2f348efd7e 273 packets[i].state = TO_BE_SENT;
earlz 0:fa2f348efd7e 274 if(timing > 0) {
earlz 0:fa2f348efd7e 275 packets[i].registration = _reg_timer.read_us();
earlz 0:fa2f348efd7e 276 packets[i].timing = timing;
earlz 0:fa2f348efd7e 277 }
earlz 0:fa2f348efd7e 278 return i;
earlz 0:fa2f348efd7e 279 }
earlz 0:fa2f348efd7e 280
earlz 0:fa2f348efd7e 281 this->_error(PACKETS_BUFFER_FULL, MAX_PACKETS);
earlz 0:fa2f348efd7e 282 return FAIL;
earlz 0:fa2f348efd7e 283 }
earlz 0:fa2f348efd7e 284
earlz 0:fa2f348efd7e 285
earlz 0:fa2f348efd7e 286 /* Update the state of the send list:
earlz 0:fa2f348efd7e 287 check if there are packets to be sent or to be erased
earlz 0:fa2f348efd7e 288 if correctly delivered */
earlz 0:fa2f348efd7e 289
earlz 0:fa2f348efd7e 290 void PJON::update() {
earlz 0:fa2f348efd7e 291 for(uint8_t i = 0; i < MAX_PACKETS; i++) {
earlz 0:fa2f348efd7e 292 if(packets[i].state != NULL)
earlz 0:fa2f348efd7e 293 if(_reg_timer.read_us() - packets[i].registration > packets[i].timing + (packets[i].attempts * packets[i].attempts)) //pow((float)packets[i].attempts, 2)) //avoid float operation
earlz 0:fa2f348efd7e 294 packets[i].state = send_string(packets[i].device_id, packets[i].content, packets[i].length);
earlz 0:fa2f348efd7e 295
earlz 0:fa2f348efd7e 296 if(packets[i].state == ACK) {
earlz 0:fa2f348efd7e 297 if(!packets[i].timing)
earlz 0:fa2f348efd7e 298 this->remove(i);
earlz 0:fa2f348efd7e 299 else {
earlz 0:fa2f348efd7e 300 packets[i].attempts = 0;
earlz 0:fa2f348efd7e 301 packets[i].registration = _reg_timer.read_us();
earlz 0:fa2f348efd7e 302 packets[i].state = TO_BE_SENT;
earlz 0:fa2f348efd7e 303 }
earlz 0:fa2f348efd7e 304 }
earlz 0:fa2f348efd7e 305 if(packets[i].state == FAIL) {
earlz 0:fa2f348efd7e 306 packets[i].attempts++;
earlz 0:fa2f348efd7e 307
earlz 0:fa2f348efd7e 308 if(packets[i].attempts > MAX_ATTEMPTS) {
earlz 0:fa2f348efd7e 309 this->_error(CONNECTION_LOST, packets[i].device_id);
earlz 0:fa2f348efd7e 310 if(!packets[i].timing)
earlz 0:fa2f348efd7e 311 this->remove(i);
earlz 0:fa2f348efd7e 312 else {
earlz 0:fa2f348efd7e 313 packets[i].attempts = 0;
earlz 0:fa2f348efd7e 314 packets[i].registration = _reg_timer.read_us();
earlz 0:fa2f348efd7e 315 packets[i].state = TO_BE_SENT;
earlz 0:fa2f348efd7e 316 }
earlz 0:fa2f348efd7e 317 }
earlz 0:fa2f348efd7e 318 }
earlz 0:fa2f348efd7e 319 }
earlz 0:fa2f348efd7e 320 }
earlz 0:fa2f348efd7e 321
earlz 0:fa2f348efd7e 322
earlz 0:fa2f348efd7e 323 /* Remove a packet from the send list: */
earlz 0:fa2f348efd7e 324
earlz 0:fa2f348efd7e 325 void PJON::remove(int id) {
earlz 0:fa2f348efd7e 326 free(packets[id].content);
earlz 0:fa2f348efd7e 327 packets[id].attempts = 0;
earlz 0:fa2f348efd7e 328 packets[id].device_id = NULL;
earlz 0:fa2f348efd7e 329 packets[id].length = NULL;
earlz 0:fa2f348efd7e 330 packets[id].state = NULL;
earlz 0:fa2f348efd7e 331 packets[id].registration = NULL;
earlz 0:fa2f348efd7e 332 }
earlz 0:fa2f348efd7e 333
earlz 0:fa2f348efd7e 334
earlz 0:fa2f348efd7e 335 /* Syncronize with transmitter:
earlz 0:fa2f348efd7e 336 This function is used only in byte syncronization.
earlz 0:fa2f348efd7e 337 READ_DELAY has to be tuned to correctly send and
earlz 0:fa2f348efd7e 338 receive transmissions because this variable shifts
earlz 0:fa2f348efd7e 339 in which portion of the bit, the reading will be
earlz 0:fa2f348efd7e 340 executed by the next read_byte function */
earlz 0:fa2f348efd7e 341
earlz 0:fa2f348efd7e 342 uint8_t PJON::syncronization_bit() {
earlz 0:fa2f348efd7e 343 wait_us((BIT_WIDTH / 2) - READ_DELAY);
earlz 0:fa2f348efd7e 344 uint8_t bit_value = _input_pin; //digitalReadFast(_input_pin);
earlz 0:fa2f348efd7e 345 wait_us(BIT_WIDTH / 2);
earlz 0:fa2f348efd7e 346 return bit_value;
earlz 0:fa2f348efd7e 347 }
earlz 0:fa2f348efd7e 348
earlz 0:fa2f348efd7e 349
earlz 0:fa2f348efd7e 350 /* Check if a byte is coming from the pin:
earlz 0:fa2f348efd7e 351 This function is looking for padding bits before a byte.
earlz 0:fa2f348efd7e 352 If value is 1 for more than ACCEPTANCE and after
earlz 0:fa2f348efd7e 353 that comes a 0 probably a byte is coming:
earlz 0:fa2f348efd7e 354 ________
earlz 0:fa2f348efd7e 355 | Init |
earlz 0:fa2f348efd7e 356 |--------|
earlz 0:fa2f348efd7e 357 |_____ |
earlz 0:fa2f348efd7e 358 | | | |
earlz 0:fa2f348efd7e 359 |1 | |0 |
earlz 0:fa2f348efd7e 360 |__|__|__|
earlz 0:fa2f348efd7e 361 |
earlz 0:fa2f348efd7e 362 ACCEPTANCE */
earlz 0:fa2f348efd7e 363
earlz 0:fa2f348efd7e 364 int PJON::receive_byte() {
earlz 0:fa2f348efd7e 365 Timer t;
earlz 0:fa2f348efd7e 366 /* Initialize the pin and set it to LOW to reduce interference */
earlz 0:fa2f348efd7e 367 _input_pin.input(); //pinModeFast(_input_pin, INPUT);
earlz 0:fa2f348efd7e 368 _input_pin = 0; //digitalWriteFast(_input_pin, LOW);
earlz 0:fa2f348efd7e 369 //unsigned long time = micros();
earlz 0:fa2f348efd7e 370 t.start();
earlz 0:fa2f348efd7e 371 int time=0;
earlz 0:fa2f348efd7e 372 /* Do nothing until the pin stops to be HIGH or passed more time than
earlz 0:fa2f348efd7e 373 BIT_SPACER duration (freak condition used to avoid micros() overflow bug) */ //MBED needed?
earlz 0:fa2f348efd7e 374 while (_input_pin && !(t.read_us() >= BIT_SPACER));
earlz 2:5648483c5dbc 375
earlz 0:fa2f348efd7e 376 /* Save how much time passed */
earlz 0:fa2f348efd7e 377 time = t.read_us();
earlz 0:fa2f348efd7e 378 /* is for sure less than BIT_SPACER, and if is more than ACCEPTANCE
earlz 0:fa2f348efd7e 379 (a minimum HIGH duration) and what is coming after is a LOW bit
earlz 0:fa2f348efd7e 380 probably a byte is coming so try to receive it. */
earlz 2:5648483c5dbc 381 t.stop();
earlz 0:fa2f348efd7e 382 if(time >= ACCEPTANCE && !this->syncronization_bit()){
earlz 2:5648483c5dbc 383 DigitalOut myled(LED3);
earlz 2:5648483c5dbc 384 myled = 1;
earlz 0:fa2f348efd7e 385 return (int)this->read_byte();
earlz 0:fa2f348efd7e 386 }
earlz 0:fa2f348efd7e 387
earlz 0:fa2f348efd7e 388 return FAIL;
earlz 0:fa2f348efd7e 389 }
earlz 0:fa2f348efd7e 390
earlz 0:fa2f348efd7e 391
earlz 0:fa2f348efd7e 392 /* Read a byte from the pin */
earlz 0:fa2f348efd7e 393
earlz 0:fa2f348efd7e 394 uint8_t PJON::read_byte() {
earlz 0:fa2f348efd7e 395 uint8_t byte_value = 0xB00000000;
earlz 0:fa2f348efd7e 396 wait_us(BIT_WIDTH / 2);
earlz 0:fa2f348efd7e 397 for (uint8_t i = 0; i < 8; i++) {
earlz 0:fa2f348efd7e 398 byte_value += _input_pin << i;
earlz 0:fa2f348efd7e 399 wait_us(BIT_WIDTH);
earlz 0:fa2f348efd7e 400 }
earlz 0:fa2f348efd7e 401 return byte_value;
earlz 0:fa2f348efd7e 402 }
earlz 0:fa2f348efd7e 403
earlz 0:fa2f348efd7e 404
earlz 0:fa2f348efd7e 405 /* Try to receive a packet from the pin: */
earlz 0:fa2f348efd7e 406
earlz 0:fa2f348efd7e 407 int PJON::receive() {
earlz 0:fa2f348efd7e 408 int package_length = PACKET_MAX_LENGTH;
earlz 0:fa2f348efd7e 409 uint8_t CRC = 0;
earlz 0:fa2f348efd7e 410
earlz 0:fa2f348efd7e 411 for (uint8_t i = 0; i <= package_length; i++) {
earlz 0:fa2f348efd7e 412 data[i] = this->receive_byte();
earlz 0:fa2f348efd7e 413
earlz 0:fa2f348efd7e 414 if (data[i] == FAIL) return FAIL;
earlz 0:fa2f348efd7e 415
earlz 0:fa2f348efd7e 416 if(i == 0 && data[i] != _device_id && data[i] != BROADCAST)
earlz 0:fa2f348efd7e 417 return BUSY;
earlz 0:fa2f348efd7e 418
earlz 0:fa2f348efd7e 419 if(i == 1)
earlz 0:fa2f348efd7e 420 if(data[i] > 0 && data[i] < PACKET_MAX_LENGTH)
earlz 0:fa2f348efd7e 421 package_length = data[i];
earlz 0:fa2f348efd7e 422 else return FAIL;
earlz 0:fa2f348efd7e 423
earlz 0:fa2f348efd7e 424 CRC ^= data[i];
earlz 0:fa2f348efd7e 425 }
earlz 0:fa2f348efd7e 426
earlz 0:fa2f348efd7e 427 _input_pin.output(); //pinModeFast(_input_pin, OUTPUT);
earlz 0:fa2f348efd7e 428
earlz 0:fa2f348efd7e 429 if (!CRC) {
earlz 0:fa2f348efd7e 430 if(data[0] != BROADCAST) {
earlz 0:fa2f348efd7e 431 this->send_byte(ACK);
earlz 0:fa2f348efd7e 432 _input_pin = 0; //digitalWriteFast(_input_pin, LOW);
earlz 0:fa2f348efd7e 433 }
earlz 0:fa2f348efd7e 434 this->_receiver(data[1] - 3, data + 2);
earlz 0:fa2f348efd7e 435 return ACK;
earlz 0:fa2f348efd7e 436 } else {
earlz 0:fa2f348efd7e 437 if(data[0] != BROADCAST) {
earlz 0:fa2f348efd7e 438 this->send_byte(NAK);
earlz 0:fa2f348efd7e 439 _input_pin = 0; //digitalWriteFast(_input_pin, LOW);
earlz 0:fa2f348efd7e 440 }
earlz 0:fa2f348efd7e 441 return NAK;
earlz 0:fa2f348efd7e 442 }
earlz 0:fa2f348efd7e 443 }
earlz 0:fa2f348efd7e 444
earlz 0:fa2f348efd7e 445
earlz 0:fa2f348efd7e 446 /* Try to receive a packet from the pin repeatedly with a maximum duration: */
earlz 0:fa2f348efd7e 447
earlz 0:fa2f348efd7e 448 int PJON::receive(unsigned long duration) {
earlz 0:fa2f348efd7e 449 int response;
earlz 0:fa2f348efd7e 450 Timer t;
earlz 0:fa2f348efd7e 451 t.start();
earlz 0:fa2f348efd7e 452 //long time = micros();
earlz 0:fa2f348efd7e 453 /* (freak condition used to avoid micros() overflow bug) */
earlz 0:fa2f348efd7e 454 while(!(t.read_us() >= duration)) {
earlz 0:fa2f348efd7e 455 response = this->receive();
earlz 0:fa2f348efd7e 456 if(response == ACK){
earlz 0:fa2f348efd7e 457 t.stop();
earlz 0:fa2f348efd7e 458 return ACK;
earlz 0:fa2f348efd7e 459 }
earlz 0:fa2f348efd7e 460 }
earlz 0:fa2f348efd7e 461 return response;
earlz 0:fa2f348efd7e 462 }