Thomas Cauwelier / Mbed 2 deprecated visible_light_communication

Dependencies:   SoftSerial SDFileSystem mbed wave_player

Committer:
Thomas Cauwelier
Date:
Sat May 13 16:21:17 2017 +0200
Revision:
20:d2a8daeb6eb7
Parent:
19:822d93e0bf34
Child:
21:2a91babf5a6d
change start bit transmission to send a pattern of 4 bits (0101)
add start bits detection when receiving

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 uint32_t overhead_us = 200 * 1000000 / SystemCoreClock;
Thomas Cauwelier 20:d2a8daeb6eb7 9
Desertification 16:1a0589d846bf 10 MySoftSerial::MySoftSerial(PinName TX, PinName RX, const char *name) : SoftSerial(TX, RX, name) {
Thomas Cauwelier 20:d2a8daeb6eb7 11 max_time_between_transmission_us = 100000;
Thomas Cauwelier 20:d2a8daeb6eb7 12 calc_required_correction_symbols();
Thomas Cauwelier 17:8683abdc1912 13 format(16, SoftSerial::None, 1);
Thomas Cauwelier 20:d2a8daeb6eb7 14 start_bits = 4;
Thomas Cauwelier 20:d2a8daeb6eb7 15 dc_offset_timer.reset();
Thomas Cauwelier 20:d2a8daeb6eb7 16 dc_offset_timer.start();
Thomas Cauwelier 20:d2a8daeb6eb7 17 }
Thomas Cauwelier 20:d2a8daeb6eb7 18
Thomas Cauwelier 20:d2a8daeb6eb7 19 void MySoftSerial::calc_required_correction_symbols() {
Thomas Cauwelier 20:d2a8daeb6eb7 20 required_correction_transmissions = (int) ceil(30000.0 / (16 * bit_period));
Thomas Cauwelier 15:75f9bd5d7659 21 }
Thomas Cauwelier 15:75f9bd5d7659 22
Thomas Cauwelier 15:75f9bd5d7659 23 MySoftSerial::~MySoftSerial() {
Thomas Cauwelier 15:75f9bd5d7659 24
Thomas Cauwelier 15:75f9bd5d7659 25 }
Thomas Cauwelier 15:75f9bd5d7659 26
Thomas Cauwelier 15:75f9bd5d7659 27 int MySoftSerial::putc(int c) {
Thomas Cauwelier 17:8683abdc1912 28 c = Manchester::encode(c);
Thomas Cauwelier 20:d2a8daeb6eb7 29 // check if last transmission was not too long ago
Thomas Cauwelier 20:d2a8daeb6eb7 30 dc_offset_timer.stop();
Thomas Cauwelier 20:d2a8daeb6eb7 31 if (dc_offset_timer.read_us() > max_time_between_transmission_us) {
Thomas Cauwelier 20:d2a8daeb6eb7 32 // transmission was too long ago, must correct the dc offset
Thomas Cauwelier 19:822d93e0bf34 33 correct_dc_offset();
Thomas Cauwelier 19:822d93e0bf34 34 }
Thomas Cauwelier 15:75f9bd5d7659 35 return _putc(c);
Thomas Cauwelier 15:75f9bd5d7659 36 }
Thomas Cauwelier 15:75f9bd5d7659 37
Thomas Cauwelier 15:75f9bd5d7659 38 int MySoftSerial::getc() {
Thomas Cauwelier 19:822d93e0bf34 39 int character = _getc();
Thomas Cauwelier 19:822d93e0bf34 40 return Manchester::decode(character);
Thomas Cauwelier 17:8683abdc1912 41 }
Thomas Cauwelier 17:8683abdc1912 42
Thomas Cauwelier 17:8683abdc1912 43 void MySoftSerial::prepare_tx(int c) {
Thomas Cauwelier 20:d2a8daeb6eb7 44 // _char is transmitted lsb first
Thomas Cauwelier 20:d2a8daeb6eb7 45 _char = c << start_bits; // make room for start bits
Thomas Cauwelier 20:d2a8daeb6eb7 46 _char |= 0b1010; //add start bits (lsb first)
Thomas Cauwelier 20:d2a8daeb6eb7 47 _char |= 0xFFFF << (start_bits + _bits); // pad with stop bits
Thomas Cauwelier 20:d2a8daeb6eb7 48 _char &= ~(1<<_total_bits); // zero after last stop bit ~(1<<_total_bits) = ...111101111...
Thomas Cauwelier 15:75f9bd5d7659 49 }
Thomas Cauwelier 17:8683abdc1912 50
Thomas Cauwelier 17:8683abdc1912 51 void MySoftSerial::baud(int baudrate) {
Thomas Cauwelier 17:8683abdc1912 52 SoftSerial::baud(baudrate);
Thomas Cauwelier 20:d2a8daeb6eb7 53 calc_required_correction_symbols();
Thomas Cauwelier 17:8683abdc1912 54 }
Thomas Cauwelier 17:8683abdc1912 55
Thomas Cauwelier 17:8683abdc1912 56 int MySoftSerial::readable() {
Thomas Cauwelier 17:8683abdc1912 57 return SoftSerial::readable();
Thomas Cauwelier 17:8683abdc1912 58 }
Thomas Cauwelier 17:8683abdc1912 59
Thomas Cauwelier 17:8683abdc1912 60 int MySoftSerial::writeable() {
Thomas Cauwelier 17:8683abdc1912 61 return SoftSerial::writeable();
Thomas Cauwelier 17:8683abdc1912 62 }
Thomas Cauwelier 19:822d93e0bf34 63
Thomas Cauwelier 19:822d93e0bf34 64 void MySoftSerial::correct_dc_offset() {
Thomas Cauwelier 20:d2a8daeb6eb7 65 for (int i = 0; i < required_correction_transmissions; ++i) {
Thomas Cauwelier 20:d2a8daeb6eb7 66 //16 bit_periods
Thomas Cauwelier 19:822d93e0bf34 67 tx->write(0);
Thomas Cauwelier 19:822d93e0bf34 68 wait_us(bit_period * 12); // send 12 zeros
Thomas Cauwelier 19:822d93e0bf34 69 tx->write(1);
Thomas Cauwelier 19:822d93e0bf34 70 wait_us(bit_period * 4); // send 4 ones
Thomas Cauwelier 19:822d93e0bf34 71 }
Thomas Cauwelier 19:822d93e0bf34 72 }
Thomas Cauwelier 20:d2a8daeb6eb7 73
Thomas Cauwelier 20:d2a8daeb6eb7 74 void MySoftSerial::rx_gpio_irq_handler(void) {
Thomas Cauwelier 20:d2a8daeb6eb7 75 rxticker.prime();
Thomas Cauwelier 20:d2a8daeb6eb7 76 rxticker.setNext(bit_period + (bit_period >> 1) - overhead_us); // jump 1.5 bit periods
Thomas Cauwelier 20:d2a8daeb6eb7 77 rx->fall(NULL);
Thomas Cauwelier 20:d2a8daeb6eb7 78 rxticker.attach(this, &MySoftSerial::rx_detect_start);
Thomas Cauwelier 20:d2a8daeb6eb7 79 start_bit = 1; // start from second bit
Thomas Cauwelier 20:d2a8daeb6eb7 80 rx_bit = 0;
Thomas Cauwelier 20:d2a8daeb6eb7 81 rx_error = false;
Thomas Cauwelier 20:d2a8daeb6eb7 82 }
Thomas Cauwelier 20:d2a8daeb6eb7 83
Thomas Cauwelier 20:d2a8daeb6eb7 84 void MySoftSerial::rx_detect_start(void){
Thomas Cauwelier 20:d2a8daeb6eb7 85 int val = rx->read();
Thomas Cauwelier 20:d2a8daeb6eb7 86
Thomas Cauwelier 20:d2a8daeb6eb7 87 // check start pattern
Thomas Cauwelier 20:d2a8daeb6eb7 88 // todo store pattern in array or int
Thomas Cauwelier 20:d2a8daeb6eb7 89 bool ok;
Thomas Cauwelier 20:d2a8daeb6eb7 90 switch(start_bit){
Thomas Cauwelier 20:d2a8daeb6eb7 91 case 0:
Thomas Cauwelier 20:d2a8daeb6eb7 92 ok = val==0;
Thomas Cauwelier 20:d2a8daeb6eb7 93 break;
Thomas Cauwelier 20:d2a8daeb6eb7 94 case 1:
Thomas Cauwelier 20:d2a8daeb6eb7 95 ok = val==1;
Thomas Cauwelier 20:d2a8daeb6eb7 96 break;
Thomas Cauwelier 20:d2a8daeb6eb7 97 case 2:
Thomas Cauwelier 20:d2a8daeb6eb7 98 ok = val==0;
Thomas Cauwelier 20:d2a8daeb6eb7 99 break;
Thomas Cauwelier 20:d2a8daeb6eb7 100 case 3:
Thomas Cauwelier 20:d2a8daeb6eb7 101 ok = val==1;
Thomas Cauwelier 20:d2a8daeb6eb7 102 rxticker.attach(this, &MySoftSerial::tx_handler);
Thomas Cauwelier 20:d2a8daeb6eb7 103 break;
Thomas Cauwelier 20:d2a8daeb6eb7 104 default:
Thomas Cauwelier 20:d2a8daeb6eb7 105 ok = false;
Thomas Cauwelier 20:d2a8daeb6eb7 106 }
Thomas Cauwelier 20:d2a8daeb6eb7 107
Thomas Cauwelier 20:d2a8daeb6eb7 108 if(ok){
Thomas Cauwelier 20:d2a8daeb6eb7 109 rx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 110 rxticker.setNext(bit_period);
Thomas Cauwelier 20:d2a8daeb6eb7 111 } else {
Thomas Cauwelier 20:d2a8daeb6eb7 112 // start pattern was not correct, this is not a data packet
Thomas Cauwelier 20:d2a8daeb6eb7 113 rxticker.detach();
Thomas Cauwelier 20:d2a8daeb6eb7 114 rx->fall(this, &SoftSerial::rx_gpio_irq_handler);
Thomas Cauwelier 20:d2a8daeb6eb7 115 }
Thomas Cauwelier 20:d2a8daeb6eb7 116 }
Thomas Cauwelier 20:d2a8daeb6eb7 117
Thomas Cauwelier 20:d2a8daeb6eb7 118 void MySoftSerial::format(int bits, SoftSerial::Parity parity, int stop_bits) {
Thomas Cauwelier 20:d2a8daeb6eb7 119 SoftSerial::format(bits, parity, stop_bits);
Thomas Cauwelier 20:d2a8daeb6eb7 120 _total_bits = 4 + _bits + _stop_bits;
Thomas Cauwelier 20:d2a8daeb6eb7 121 }
Thomas Cauwelier 20:d2a8daeb6eb7 122
Thomas Cauwelier 20:d2a8daeb6eb7 123 void MySoftSerial::tx_handler(void) {
Thomas Cauwelier 20:d2a8daeb6eb7 124 if (tx_bit == _total_bits) {
Thomas Cauwelier 20:d2a8daeb6eb7 125 tx_bit = -1;
Thomas Cauwelier 20:d2a8daeb6eb7 126 // transmission done, start measuring time until next transmission
Thomas Cauwelier 20:d2a8daeb6eb7 127 dc_offset_timer.reset();
Thomas Cauwelier 20:d2a8daeb6eb7 128 dc_offset_timer.start();
Thomas Cauwelier 20:d2a8daeb6eb7 129
Thomas Cauwelier 20:d2a8daeb6eb7 130 fpointer[TxIrq].call();
Thomas Cauwelier 20:d2a8daeb6eb7 131 return;
Thomas Cauwelier 20:d2a8daeb6eb7 132 }
Thomas Cauwelier 20:d2a8daeb6eb7 133
Thomas Cauwelier 20:d2a8daeb6eb7 134 //Flip output
Thomas Cauwelier 20:d2a8daeb6eb7 135 int cur_out = tx->read();
Thomas Cauwelier 20:d2a8daeb6eb7 136 tx->write(!cur_out);
Thomas Cauwelier 20:d2a8daeb6eb7 137
Thomas Cauwelier 20:d2a8daeb6eb7 138 //Calculate when to do it again
Thomas Cauwelier 20:d2a8daeb6eb7 139 int count = bit_period;
Thomas Cauwelier 20:d2a8daeb6eb7 140 tx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 141 while(((_char >> tx_bit) & 0x01) == !cur_out) {
Thomas Cauwelier 20:d2a8daeb6eb7 142 count+=bit_period;
Thomas Cauwelier 20:d2a8daeb6eb7 143 tx_bit++;
Thomas Cauwelier 20:d2a8daeb6eb7 144 }
Thomas Cauwelier 20:d2a8daeb6eb7 145
Thomas Cauwelier 20:d2a8daeb6eb7 146 txticker.setNext(count);
Thomas Cauwelier 20:d2a8daeb6eb7 147 }