Thomas Cauwelier / Mbed 2 deprecated visible_light_communication

Dependencies:   SoftSerial SDFileSystem mbed wave_player

Committer:
Desertification
Date:
Tue May 16 19:29:56 2017 +0000
Revision:
21:2a91babf5a6d
Parent:
20:d2a8daeb6eb7
Child:
22:c821bfae25d7
finding rx bug

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