Thomas Cauwelier / Mbed 2 deprecated visible_light_communication

Dependencies:   SoftSerial SDFileSystem mbed wave_player

Committer:
Desertification
Date:
Wed May 17 09:43:38 2017 +0000
Revision:
29:c2d95d88ee0b
Parent:
23:121e3235ccfa
DONE (for now)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Thomas Cauwelier 15:75f9bd5d7659 1 //
Thomas Cauwelier 15:75f9bd5d7659 2 // Created by thoma on 10-May-17.
Thomas Cauwelier 15:75f9bd5d7659 3 //
Thomas Cauwelier 15:75f9bd5d7659 4
Thomas Cauwelier 15:75f9bd5d7659 5 #include "MySoftSerial.h"
Thomas Cauwelier 17:8683abdc1912 6 #include "Manchester.h"
Thomas Cauwelier 15:75f9bd5d7659 7
Thomas Cauwelier 20:d2a8daeb6eb7 8
Thomas Cauwelier 22:c821bfae25d7 9 MySoftSerial::MySoftSerial(PinName TX, PinName RX, const char *name) {
Thomas Cauwelier 22:c821bfae25d7 10 //MySoftSerial::MySoftSerial(PinName TX, PinName RX, const char *name) : SoftSerial(TX, RX, name) {
Thomas Cauwelier 22:c821bfae25d7 11 tx_en = rx_en = false;
Thomas Cauwelier 22:c821bfae25d7 12 read_buffer = 0;
Thomas Cauwelier 22:c821bfae25d7 13 if (TX != NC) {
Thomas Cauwelier 22:c821bfae25d7 14 tx = new DigitalOut(TX);
Thomas Cauwelier 22:c821bfae25d7 15 tx_en = true;
Thomas Cauwelier 22:c821bfae25d7 16 tx->write(1);
Thomas Cauwelier 22:c821bfae25d7 17 tx_bit = -1;
Thomas Cauwelier 22:c821bfae25d7 18 txticker.attach(this, &MySoftSerial::tx_handler);
Thomas Cauwelier 22:c821bfae25d7 19 }
Thomas Cauwelier 22:c821bfae25d7 20 if (RX != NC) {
Thomas Cauwelier 22:c821bfae25d7 21 rx = new InterruptIn(RX);
Thomas Cauwelier 22:c821bfae25d7 22 rx_en = true;
Thomas Cauwelier 22:c821bfae25d7 23 out_valid = false;
Thomas Cauwelier 22:c821bfae25d7 24 rxticker.attach(this, &MySoftSerial::rx_handler);
Thomas Cauwelier 22:c821bfae25d7 25 rx->fall(this, &MySoftSerial::rx_gpio_irq_handler);
Thomas Cauwelier 22:c821bfae25d7 26 }
Thomas Cauwelier 22:c821bfae25d7 27
Thomas Cauwelier 22:c821bfae25d7 28 baud(9600);
Thomas Cauwelier 22:c821bfae25d7 29
Desertification 21:2a91babf5a6d 30 max_time_between_transmission_us = 10000;
Thomas Cauwelier 20:d2a8daeb6eb7 31 calc_required_correction_symbols();
Thomas Cauwelier 22:c821bfae25d7 32 format(16, MySoftSerial::None, 1);
Thomas Cauwelier 20:d2a8daeb6eb7 33 start_bits = 4;
Thomas Cauwelier 20:d2a8daeb6eb7 34 dc_offset_timer.reset();
Thomas Cauwelier 20:d2a8daeb6eb7 35 dc_offset_timer.start();
Desertification 21:2a91babf5a6d 36 overhead_us = 200 * 1000000 / SystemCoreClock;
Thomas Cauwelier 22:c821bfae25d7 37
Thomas Cauwelier 20:d2a8daeb6eb7 38 }
Thomas Cauwelier 20:d2a8daeb6eb7 39
Thomas Cauwelier 20:d2a8daeb6eb7 40 void MySoftSerial::calc_required_correction_symbols() {
Thomas Cauwelier 20:d2a8daeb6eb7 41 required_correction_transmissions = (int) ceil(30000.0 / (16 * bit_period));
Thomas Cauwelier 15:75f9bd5d7659 42 }
Thomas Cauwelier 15:75f9bd5d7659 43
Thomas Cauwelier 15:75f9bd5d7659 44 MySoftSerial::~MySoftSerial() {
Thomas Cauwelier 22:c821bfae25d7 45 if (tx_en)
Thomas Cauwelier 22:c821bfae25d7 46 delete(tx);
Thomas Cauwelier 22:c821bfae25d7 47 if (rx_en)
Thomas Cauwelier 22:c821bfae25d7 48 delete(rx);
Thomas Cauwelier 15:75f9bd5d7659 49 }
Thomas Cauwelier 15:75f9bd5d7659 50
Thomas Cauwelier 15:75f9bd5d7659 51 int MySoftSerial::putc(int c) {
Thomas Cauwelier 17:8683abdc1912 52 c = Manchester::encode(c);
Thomas Cauwelier 20:d2a8daeb6eb7 53 // check if last transmission was not too long ago
Thomas Cauwelier 20:d2a8daeb6eb7 54 dc_offset_timer.stop();
Thomas Cauwelier 20:d2a8daeb6eb7 55 if (dc_offset_timer.read_us() > max_time_between_transmission_us) {
Thomas Cauwelier 20:d2a8daeb6eb7 56 // transmission was too long ago, must correct the dc offset
Thomas Cauwelier 19:822d93e0bf34 57 correct_dc_offset();
Thomas Cauwelier 19:822d93e0bf34 58 }
Thomas Cauwelier 15:75f9bd5d7659 59 return _putc(c);
Thomas Cauwelier 15:75f9bd5d7659 60 }
Thomas Cauwelier 15:75f9bd5d7659 61
Desertification 21:2a91babf5a6d 62 int MySoftSerial::_putc(int c)
Desertification 21:2a91babf5a6d 63 {
Desertification 21:2a91babf5a6d 64 while(!writeable());
Desertification 21:2a91babf5a6d 65 prepare_tx(c);
Desertification 21:2a91babf5a6d 66 tx_bit = 0;
Desertification 21:2a91babf5a6d 67 txticker.prime();
Desertification 21:2a91babf5a6d 68 tx_handler();
Desertification 21:2a91babf5a6d 69 return 0;
Desertification 21:2a91babf5a6d 70 }
Desertification 21:2a91babf5a6d 71
Thomas Cauwelier 15:75f9bd5d7659 72 int MySoftSerial::getc() {
Thomas Cauwelier 19:822d93e0bf34 73 int character = _getc();
Thomas Cauwelier 19:822d93e0bf34 74 return Manchester::decode(character);
Thomas Cauwelier 17:8683abdc1912 75 }
Thomas Cauwelier 17:8683abdc1912 76
Thomas Cauwelier 17:8683abdc1912 77 void MySoftSerial::prepare_tx(int c) {
Thomas Cauwelier 20:d2a8daeb6eb7 78 // _char is transmitted lsb first
Thomas Cauwelier 20:d2a8daeb6eb7 79 _char = c << start_bits; // make room for start bits
Thomas Cauwelier 20:d2a8daeb6eb7 80 _char |= 0b1010; //add start bits (lsb first)
Thomas Cauwelier 20:d2a8daeb6eb7 81 _char |= 0xFFFF << (start_bits + _bits); // pad with stop bits
Thomas Cauwelier 20:d2a8daeb6eb7 82 _char &= ~(1<<_total_bits); // zero after last stop bit ~(1<<_total_bits) = ...111101111...
Thomas Cauwelier 15:75f9bd5d7659 83 }
Thomas Cauwelier 17:8683abdc1912 84
Thomas Cauwelier 17:8683abdc1912 85 void MySoftSerial::baud(int baudrate) {
Thomas Cauwelier 22:c821bfae25d7 86 bit_period = 1000000 / baudrate;
Thomas Cauwelier 20:d2a8daeb6eb7 87 calc_required_correction_symbols();
Thomas Cauwelier 17:8683abdc1912 88 }
Thomas Cauwelier 17:8683abdc1912 89
Thomas Cauwelier 17:8683abdc1912 90 int MySoftSerial::readable() {
Thomas Cauwelier 22:c821bfae25d7 91 return out_valid;
Thomas Cauwelier 17:8683abdc1912 92 }
Thomas Cauwelier 17:8683abdc1912 93
Thomas Cauwelier 17:8683abdc1912 94 int MySoftSerial::writeable() {
Thomas Cauwelier 22:c821bfae25d7 95 if (!tx_en)
Thomas Cauwelier 22:c821bfae25d7 96 return false;
Thomas Cauwelier 22:c821bfae25d7 97 if (tx_bit == -1)
Thomas Cauwelier 22:c821bfae25d7 98 return true;
Thomas Cauwelier 22:c821bfae25d7 99 return false;
Thomas Cauwelier 17:8683abdc1912 100 }
Thomas Cauwelier 19:822d93e0bf34 101
Thomas Cauwelier 19:822d93e0bf34 102 void MySoftSerial::correct_dc_offset() {
Thomas Cauwelier 20:d2a8daeb6eb7 103 for (int i = 0; i < required_correction_transmissions; ++i) {
Thomas Cauwelier 20:d2a8daeb6eb7 104 //16 bit_periods
Thomas Cauwelier 19:822d93e0bf34 105 tx->write(0);
Thomas Cauwelier 19:822d93e0bf34 106 wait_us(bit_period * 12); // send 12 zeros
Thomas Cauwelier 19:822d93e0bf34 107 tx->write(1);
Thomas Cauwelier 19:822d93e0bf34 108 wait_us(bit_period * 4); // send 4 ones
Thomas Cauwelier 19:822d93e0bf34 109 }
Thomas Cauwelier 19:822d93e0bf34 110 }
Thomas Cauwelier 20:d2a8daeb6eb7 111
Thomas Cauwelier 22:c821bfae25d7 112 int MySoftSerial::_getc( void ) {
Thomas Cauwelier 22:c821bfae25d7 113 while(!readable());
Thomas Cauwelier 22:c821bfae25d7 114 out_valid = false;
Thomas Cauwelier 22:c821bfae25d7 115 return out_buffer;
Thomas Cauwelier 22:c821bfae25d7 116 }
Thomas Cauwelier 22:c821bfae25d7 117
Thomas Cauwelier 20:d2a8daeb6eb7 118 void MySoftSerial::rx_gpio_irq_handler(void) {
Thomas Cauwelier 20:d2a8daeb6eb7 119 rxticker.prime();
Thomas Cauwelier 20:d2a8daeb6eb7 120 rxticker.setNext(bit_period + (bit_period >> 1) - overhead_us); // jump 1.5 bit periods
Thomas Cauwelier 20:d2a8daeb6eb7 121 rx->fall(NULL);
Thomas Cauwelier 20:d2a8daeb6eb7 122 rxticker.attach(this, &MySoftSerial::rx_detect_start);
Thomas Cauwelier 20:d2a8daeb6eb7 123 start_bit = 1; // start from second bit
Thomas Cauwelier 20:d2a8daeb6eb7 124 rx_bit = 0;
Thomas Cauwelier 20:d2a8daeb6eb7 125 rx_error = false;
Thomas Cauwelier 20:d2a8daeb6eb7 126 }
Thomas Cauwelier 20:d2a8daeb6eb7 127
Thomas Cauwelier 20:d2a8daeb6eb7 128 void MySoftSerial::rx_detect_start(void){
Thomas Cauwelier 20:d2a8daeb6eb7 129 int val = rx->read();
Thomas Cauwelier 20:d2a8daeb6eb7 130
Thomas Cauwelier 20:d2a8daeb6eb7 131 // check start pattern
Thomas Cauwelier 20:d2a8daeb6eb7 132 // todo store pattern in array or int
Thomas Cauwelier 20:d2a8daeb6eb7 133 bool ok;
Thomas Cauwelier 20:d2a8daeb6eb7 134 switch(start_bit){
Thomas Cauwelier 20:d2a8daeb6eb7 135 case 0:
Thomas Cauwelier 20:d2a8daeb6eb7 136 ok = val==0;
Thomas Cauwelier 20:d2a8daeb6eb7 137 break;
Thomas Cauwelier 20:d2a8daeb6eb7 138 case 1:
Thomas Cauwelier 20:d2a8daeb6eb7 139 ok = val==1;
Thomas Cauwelier 20:d2a8daeb6eb7 140 break;
Thomas Cauwelier 20:d2a8daeb6eb7 141 case 2:
Thomas Cauwelier 20:d2a8daeb6eb7 142 ok = val==0;
Thomas Cauwelier 20:d2a8daeb6eb7 143 break;
Thomas Cauwelier 20:d2a8daeb6eb7 144 case 3:
Thomas Cauwelier 20:d2a8daeb6eb7 145 ok = val==1;
Desertification 21:2a91babf5a6d 146 rxticker.attach(this, &MySoftSerial::rx_handler);
Thomas Cauwelier 20:d2a8daeb6eb7 147 break;
Thomas Cauwelier 20:d2a8daeb6eb7 148 default:
Thomas Cauwelier 20:d2a8daeb6eb7 149 ok = false;
Thomas Cauwelier 20:d2a8daeb6eb7 150 }
Thomas Cauwelier 20:d2a8daeb6eb7 151
Thomas Cauwelier 20:d2a8daeb6eb7 152 if(ok){
Desertification 21:2a91babf5a6d 153 start_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 154 rxticker.setNext(bit_period);
Thomas Cauwelier 20:d2a8daeb6eb7 155 } else {
Thomas Cauwelier 20:d2a8daeb6eb7 156 // start pattern was not correct, this is not a data packet
Thomas Cauwelier 20:d2a8daeb6eb7 157 rxticker.detach();
Desertification 21:2a91babf5a6d 158 rx->fall(this, &MySoftSerial::rx_gpio_irq_handler);
Desertification 21:2a91babf5a6d 159 }
Desertification 21:2a91babf5a6d 160 }
Desertification 21:2a91babf5a6d 161
Desertification 21:2a91babf5a6d 162 void MySoftSerial::rx_handler(void) {
Desertification 21:2a91babf5a6d 163 //Receive data
Desertification 21:2a91babf5a6d 164 int val = rx->read();
Desertification 21:2a91babf5a6d 165
Desertification 21:2a91babf5a6d 166 rxticker.setNext(bit_period);
Desertification 21:2a91babf5a6d 167 rx_bit++;
Desertification 21:2a91babf5a6d 168
Desertification 21:2a91babf5a6d 169
Desertification 21:2a91babf5a6d 170 if (rx_bit <= _bits) {
Desertification 21:2a91babf5a6d 171 read_buffer |= val << (rx_bit - 1);
Desertification 21:2a91babf5a6d 172 return;
Thomas Cauwelier 20:d2a8daeb6eb7 173 }
Desertification 21:2a91babf5a6d 174
Desertification 21:2a91babf5a6d 175 //Receive parity
Desertification 21:2a91babf5a6d 176 bool parity_count;
Desertification 21:2a91babf5a6d 177 if (rx_bit == _bits + 1) {
Desertification 21:2a91babf5a6d 178 switch (_parity) {
Desertification 21:2a91babf5a6d 179 case Forced1:
Desertification 21:2a91babf5a6d 180 if (val == 0)
Desertification 21:2a91babf5a6d 181 rx_error = true;
Desertification 21:2a91babf5a6d 182 return;
Desertification 21:2a91babf5a6d 183 case Forced0:
Desertification 21:2a91babf5a6d 184 if (val == 1)
Desertification 21:2a91babf5a6d 185 rx_error = true;
Desertification 21:2a91babf5a6d 186 return;
Desertification 21:2a91babf5a6d 187 case Even:
Desertification 21:2a91babf5a6d 188 case Odd:
Desertification 21:2a91babf5a6d 189 parity_count = val;
Desertification 21:2a91babf5a6d 190 for (int i = 0; i<_bits; i++) {
Desertification 21:2a91babf5a6d 191 if (((read_buffer >> i) & 0x01) == 1)
Desertification 21:2a91babf5a6d 192 parity_count = !parity_count;
Desertification 21:2a91babf5a6d 193 }
Desertification 21:2a91babf5a6d 194 if ((parity_count) && (_parity == Even))
Desertification 21:2a91babf5a6d 195 rx_error = true;
Desertification 21:2a91babf5a6d 196 if ((!parity_count) && (_parity == Odd))
Desertification 21:2a91babf5a6d 197 rx_error = true;
Desertification 21:2a91babf5a6d 198 return;
Desertification 21:2a91babf5a6d 199 }
Desertification 21:2a91babf5a6d 200 }
Desertification 21:2a91babf5a6d 201
Desertification 21:2a91babf5a6d 202 //Receive stop
Desertification 21:2a91babf5a6d 203 if (rx_bit < _bits + (bool)_parity + _stop_bits) {
Desertification 21:2a91babf5a6d 204 if (!val)
Desertification 21:2a91babf5a6d 205 rx_error = true;
Desertification 21:2a91babf5a6d 206 return;
Desertification 21:2a91babf5a6d 207 }
Desertification 21:2a91babf5a6d 208
Desertification 21:2a91babf5a6d 209 //The last stop bit
Desertification 21:2a91babf5a6d 210 if (!val)
Desertification 21:2a91babf5a6d 211 rx_error = true;
Desertification 21:2a91babf5a6d 212
Desertification 21:2a91babf5a6d 213 if (!rx_error) {
Desertification 21:2a91babf5a6d 214 out_valid = true;
Desertification 21:2a91babf5a6d 215 out_buffer = read_buffer;
Desertification 21:2a91babf5a6d 216 fpointer[RxIrq].call();
Desertification 21:2a91babf5a6d 217 }
Desertification 21:2a91babf5a6d 218 read_buffer = 0;
Desertification 21:2a91babf5a6d 219 rxticker.detach();
Desertification 21:2a91babf5a6d 220 rx->fall(this, &MySoftSerial::rx_gpio_irq_handler);
Thomas Cauwelier 20:d2a8daeb6eb7 221 }
Thomas Cauwelier 20:d2a8daeb6eb7 222
Thomas Cauwelier 22:c821bfae25d7 223 void MySoftSerial::format(int bits, MySoftSerial::Parity parity, int stop_bits) {
Thomas Cauwelier 22:c821bfae25d7 224 _bits = bits;
Thomas Cauwelier 22:c821bfae25d7 225 _parity = parity;
Thomas Cauwelier 22:c821bfae25d7 226 _stop_bits = stop_bits;
Thomas Cauwelier 20:d2a8daeb6eb7 227 _total_bits = 4 + _bits + _stop_bits;
Thomas Cauwelier 20:d2a8daeb6eb7 228 }
Thomas Cauwelier 20:d2a8daeb6eb7 229
Thomas Cauwelier 20:d2a8daeb6eb7 230 void MySoftSerial::tx_handler(void) {
Thomas Cauwelier 20:d2a8daeb6eb7 231 if (tx_bit == _total_bits) {
Thomas Cauwelier 20:d2a8daeb6eb7 232 tx_bit = -1;
Thomas Cauwelier 20:d2a8daeb6eb7 233 // transmission done, start measuring time until next transmission
Thomas Cauwelier 20:d2a8daeb6eb7 234 dc_offset_timer.reset();
Thomas Cauwelier 20:d2a8daeb6eb7 235 dc_offset_timer.start();
Thomas Cauwelier 20:d2a8daeb6eb7 236
Thomas Cauwelier 20:d2a8daeb6eb7 237 fpointer[TxIrq].call();
Thomas Cauwelier 20:d2a8daeb6eb7 238 return;
Thomas Cauwelier 20:d2a8daeb6eb7 239 }
Thomas Cauwelier 20:d2a8daeb6eb7 240
Thomas Cauwelier 20:d2a8daeb6eb7 241 //Flip output
Thomas Cauwelier 20:d2a8daeb6eb7 242 int cur_out = tx->read();
Thomas Cauwelier 20:d2a8daeb6eb7 243 tx->write(!cur_out);
Thomas Cauwelier 20:d2a8daeb6eb7 244
Thomas Cauwelier 20:d2a8daeb6eb7 245 //Calculate when to do it again
Thomas Cauwelier 20:d2a8daeb6eb7 246 int count = bit_period;
Thomas Cauwelier 20:d2a8daeb6eb7 247 tx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 248 while(((_char >> tx_bit) & 0x01) == !cur_out) {
Thomas Cauwelier 20:d2a8daeb6eb7 249 count+=bit_period;
Thomas Cauwelier 20:d2a8daeb6eb7 250 tx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 251 }
Thomas Cauwelier 20:d2a8daeb6eb7 252
Thomas Cauwelier 20:d2a8daeb6eb7 253 txticker.setNext(count);
Thomas Cauwelier 20:d2a8daeb6eb7 254 }