Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: SoftSerial SDFileSystem mbed wave_player
MySoftSerial.cpp@20:d2a8daeb6eb7, 2017-05-13 (annotated)
- 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?
| User | Revision | Line number | New 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 | } |