Thomas Cauwelier / Mbed 2 deprecated visible_light_communication

Dependencies:   SoftSerial SDFileSystem mbed wave_player

Committer:
Thomas Cauwelier
Date:
Tue May 16 21:50:45 2017 +0200
Revision:
22:c821bfae25d7
Parent:
21:2a91babf5a6d
Child:
23:121e3235ccfa
remove inheritance

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;
Desertification 21:2a91babf5a6d 126 printf("q\n");
Thomas Cauwelier 20:d2a8daeb6eb7 127 }
Thomas Cauwelier 20:d2a8daeb6eb7 128
Thomas Cauwelier 20:d2a8daeb6eb7 129 void MySoftSerial::rx_detect_start(void){
Thomas Cauwelier 20:d2a8daeb6eb7 130 int val = rx->read();
Thomas Cauwelier 20:d2a8daeb6eb7 131
Thomas Cauwelier 20:d2a8daeb6eb7 132 // check start pattern
Thomas Cauwelier 20:d2a8daeb6eb7 133 // todo store pattern in array or int
Thomas Cauwelier 20:d2a8daeb6eb7 134 bool ok;
Thomas Cauwelier 20:d2a8daeb6eb7 135 switch(start_bit){
Thomas Cauwelier 20:d2a8daeb6eb7 136 case 0:
Thomas Cauwelier 20:d2a8daeb6eb7 137 ok = val==0;
Thomas Cauwelier 20:d2a8daeb6eb7 138 break;
Thomas Cauwelier 20:d2a8daeb6eb7 139 case 1:
Thomas Cauwelier 20:d2a8daeb6eb7 140 ok = val==1;
Desertification 21:2a91babf5a6d 141 printf("a\n");
Thomas Cauwelier 20:d2a8daeb6eb7 142 break;
Thomas Cauwelier 20:d2a8daeb6eb7 143 case 2:
Thomas Cauwelier 20:d2a8daeb6eb7 144 ok = val==0;
Desertification 21:2a91babf5a6d 145 printf("b\n");
Thomas Cauwelier 20:d2a8daeb6eb7 146 break;
Thomas Cauwelier 20:d2a8daeb6eb7 147 case 3:
Desertification 21:2a91babf5a6d 148 printf("c\n");
Thomas Cauwelier 20:d2a8daeb6eb7 149 ok = val==1;
Desertification 21:2a91babf5a6d 150 rxticker.attach(this, &MySoftSerial::rx_handler);
Thomas Cauwelier 20:d2a8daeb6eb7 151 break;
Thomas Cauwelier 20:d2a8daeb6eb7 152 default:
Desertification 21:2a91babf5a6d 153 printf("d\n");
Thomas Cauwelier 20:d2a8daeb6eb7 154 ok = false;
Thomas Cauwelier 20:d2a8daeb6eb7 155 }
Thomas Cauwelier 20:d2a8daeb6eb7 156
Thomas Cauwelier 20:d2a8daeb6eb7 157 if(ok){
Desertification 21:2a91babf5a6d 158 start_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 159 rxticker.setNext(bit_period);
Thomas Cauwelier 20:d2a8daeb6eb7 160 } else {
Thomas Cauwelier 20:d2a8daeb6eb7 161 // start pattern was not correct, this is not a data packet
Thomas Cauwelier 20:d2a8daeb6eb7 162 rxticker.detach();
Desertification 21:2a91babf5a6d 163 rx->fall(this, &MySoftSerial::rx_gpio_irq_handler);
Desertification 21:2a91babf5a6d 164 }
Desertification 21:2a91babf5a6d 165 }
Desertification 21:2a91babf5a6d 166
Desertification 21:2a91babf5a6d 167 void MySoftSerial::rx_handler(void) {
Desertification 21:2a91babf5a6d 168 //Receive data
Desertification 21:2a91babf5a6d 169 printf("%i\n",rx_bit);
Desertification 21:2a91babf5a6d 170 int val = rx->read();
Desertification 21:2a91babf5a6d 171
Desertification 21:2a91babf5a6d 172 rxticker.setNext(bit_period);
Desertification 21:2a91babf5a6d 173 rx_bit++;
Desertification 21:2a91babf5a6d 174
Desertification 21:2a91babf5a6d 175
Desertification 21:2a91babf5a6d 176 if (rx_bit <= _bits) {
Desertification 21:2a91babf5a6d 177 read_buffer |= val << (rx_bit - 1);
Desertification 21:2a91babf5a6d 178 return;
Thomas Cauwelier 20:d2a8daeb6eb7 179 }
Desertification 21:2a91babf5a6d 180
Desertification 21:2a91babf5a6d 181 //Receive parity
Desertification 21:2a91babf5a6d 182 bool parity_count;
Desertification 21:2a91babf5a6d 183 if (rx_bit == _bits + 1) {
Desertification 21:2a91babf5a6d 184 switch (_parity) {
Desertification 21:2a91babf5a6d 185 case Forced1:
Desertification 21:2a91babf5a6d 186 if (val == 0)
Desertification 21:2a91babf5a6d 187 rx_error = true;
Desertification 21:2a91babf5a6d 188 return;
Desertification 21:2a91babf5a6d 189 case Forced0:
Desertification 21:2a91babf5a6d 190 if (val == 1)
Desertification 21:2a91babf5a6d 191 rx_error = true;
Desertification 21:2a91babf5a6d 192 return;
Desertification 21:2a91babf5a6d 193 case Even:
Desertification 21:2a91babf5a6d 194 case Odd:
Desertification 21:2a91babf5a6d 195 parity_count = val;
Desertification 21:2a91babf5a6d 196 for (int i = 0; i<_bits; i++) {
Desertification 21:2a91babf5a6d 197 if (((read_buffer >> i) & 0x01) == 1)
Desertification 21:2a91babf5a6d 198 parity_count = !parity_count;
Desertification 21:2a91babf5a6d 199 }
Desertification 21:2a91babf5a6d 200 if ((parity_count) && (_parity == Even))
Desertification 21:2a91babf5a6d 201 rx_error = true;
Desertification 21:2a91babf5a6d 202 if ((!parity_count) && (_parity == Odd))
Desertification 21:2a91babf5a6d 203 rx_error = true;
Desertification 21:2a91babf5a6d 204 return;
Desertification 21:2a91babf5a6d 205 }
Desertification 21:2a91babf5a6d 206 }
Desertification 21:2a91babf5a6d 207
Desertification 21:2a91babf5a6d 208 //Receive stop
Desertification 21:2a91babf5a6d 209 if (rx_bit < _bits + (bool)_parity + _stop_bits) {
Desertification 21:2a91babf5a6d 210 if (!val)
Desertification 21:2a91babf5a6d 211 rx_error = true;
Desertification 21:2a91babf5a6d 212 return;
Desertification 21:2a91babf5a6d 213 }
Desertification 21:2a91babf5a6d 214
Desertification 21:2a91babf5a6d 215 //The last stop bit
Desertification 21:2a91babf5a6d 216 if (!val)
Desertification 21:2a91babf5a6d 217 rx_error = true;
Desertification 21:2a91babf5a6d 218
Desertification 21:2a91babf5a6d 219 if (!rx_error) {
Desertification 21:2a91babf5a6d 220 out_valid = true;
Desertification 21:2a91babf5a6d 221 out_buffer = read_buffer;
Desertification 21:2a91babf5a6d 222 fpointer[RxIrq].call();
Desertification 21:2a91babf5a6d 223 }
Desertification 21:2a91babf5a6d 224 read_buffer = 0;
Desertification 21:2a91babf5a6d 225 rxticker.detach();
Desertification 21:2a91babf5a6d 226 rx->fall(this, &MySoftSerial::rx_gpio_irq_handler);
Thomas Cauwelier 20:d2a8daeb6eb7 227 }
Thomas Cauwelier 20:d2a8daeb6eb7 228
Thomas Cauwelier 22:c821bfae25d7 229 void MySoftSerial::format(int bits, MySoftSerial::Parity parity, int stop_bits) {
Thomas Cauwelier 22:c821bfae25d7 230 _bits = bits;
Thomas Cauwelier 22:c821bfae25d7 231 _parity = parity;
Thomas Cauwelier 22:c821bfae25d7 232 _stop_bits = stop_bits;
Thomas Cauwelier 20:d2a8daeb6eb7 233 _total_bits = 4 + _bits + _stop_bits;
Thomas Cauwelier 20:d2a8daeb6eb7 234 }
Thomas Cauwelier 20:d2a8daeb6eb7 235
Thomas Cauwelier 20:d2a8daeb6eb7 236 void MySoftSerial::tx_handler(void) {
Thomas Cauwelier 20:d2a8daeb6eb7 237 if (tx_bit == _total_bits) {
Thomas Cauwelier 20:d2a8daeb6eb7 238 tx_bit = -1;
Thomas Cauwelier 20:d2a8daeb6eb7 239 // transmission done, start measuring time until next transmission
Thomas Cauwelier 20:d2a8daeb6eb7 240 dc_offset_timer.reset();
Thomas Cauwelier 20:d2a8daeb6eb7 241 dc_offset_timer.start();
Thomas Cauwelier 20:d2a8daeb6eb7 242
Thomas Cauwelier 20:d2a8daeb6eb7 243 fpointer[TxIrq].call();
Thomas Cauwelier 20:d2a8daeb6eb7 244 return;
Thomas Cauwelier 20:d2a8daeb6eb7 245 }
Thomas Cauwelier 20:d2a8daeb6eb7 246
Thomas Cauwelier 20:d2a8daeb6eb7 247 //Flip output
Thomas Cauwelier 20:d2a8daeb6eb7 248 int cur_out = tx->read();
Thomas Cauwelier 20:d2a8daeb6eb7 249 tx->write(!cur_out);
Thomas Cauwelier 20:d2a8daeb6eb7 250
Thomas Cauwelier 20:d2a8daeb6eb7 251 //Calculate when to do it again
Thomas Cauwelier 20:d2a8daeb6eb7 252 int count = bit_period;
Thomas Cauwelier 20:d2a8daeb6eb7 253 tx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 254 while(((_char >> tx_bit) & 0x01) == !cur_out) {
Thomas Cauwelier 20:d2a8daeb6eb7 255 count+=bit_period;
Thomas Cauwelier 20:d2a8daeb6eb7 256 tx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 257 }
Thomas Cauwelier 20:d2a8daeb6eb7 258
Thomas Cauwelier 20:d2a8daeb6eb7 259 txticker.setNext(count);
Thomas Cauwelier 20:d2a8daeb6eb7 260 }