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
Diff: MySoftSerial.cpp
- Revision:
- 20:d2a8daeb6eb7
- Parent:
- 19:822d93e0bf34
- Child:
- 21:2a91babf5a6d
--- a/MySoftSerial.cpp Wed May 10 18:21:14 2017 +0200
+++ b/MySoftSerial.cpp Sat May 13 16:21:17 2017 +0200
@@ -5,10 +5,19 @@
#include "MySoftSerial.h"
#include "Manchester.h"
+uint32_t overhead_us = 200 * 1000000 / SystemCoreClock;
+
MySoftSerial::MySoftSerial(PinName TX, PinName RX, const char *name) : SoftSerial(TX, RX, name) {
+ max_time_between_transmission_us = 100000;
+ calc_required_correction_symbols();
format(16, SoftSerial::None, 1);
- timer.reset();
- timer.start();
+ start_bits = 4;
+ dc_offset_timer.reset();
+ dc_offset_timer.start();
+}
+
+void MySoftSerial::calc_required_correction_symbols() {
+ required_correction_transmissions = (int) ceil(30000.0 / (16 * bit_period));
}
MySoftSerial::~MySoftSerial() {
@@ -17,8 +26,10 @@
int MySoftSerial::putc(int c) {
c = Manchester::encode(c);
- timer.stop();
- if(timer.read_us() > max_time_between_transmission_us){
+ // check if last transmission was not too long ago
+ dc_offset_timer.stop();
+ if (dc_offset_timer.read_us() > max_time_between_transmission_us) {
+ // transmission was too long ago, must correct the dc offset
correct_dc_offset();
}
return _putc(c);
@@ -26,18 +37,20 @@
int MySoftSerial::getc() {
int character = _getc();
- timer.reset();
- timer.start();
return Manchester::decode(character);
}
void MySoftSerial::prepare_tx(int c) {
-
- SoftSerial::prepare_tx(c);
+ // _char is transmitted lsb first
+ _char = c << start_bits; // make room for start bits
+ _char |= 0b1010; //add start bits (lsb first)
+ _char |= 0xFFFF << (start_bits + _bits); // pad with stop bits
+ _char &= ~(1<<_total_bits); // zero after last stop bit ~(1<<_total_bits) = ...111101111...
}
void MySoftSerial::baud(int baudrate) {
SoftSerial::baud(baudrate);
+ calc_required_correction_symbols();
}
int MySoftSerial::readable() {
@@ -49,10 +62,86 @@
}
void MySoftSerial::correct_dc_offset() {
- for (int i = 0; i < 1; ++i) {
+ for (int i = 0; i < required_correction_transmissions; ++i) {
+ //16 bit_periods
tx->write(0);
wait_us(bit_period * 12); // send 12 zeros
tx->write(1);
wait_us(bit_period * 4); // send 4 ones
}
}
+
+void MySoftSerial::rx_gpio_irq_handler(void) {
+ rxticker.prime();
+ rxticker.setNext(bit_period + (bit_period >> 1) - overhead_us); // jump 1.5 bit periods
+ rx->fall(NULL);
+ rxticker.attach(this, &MySoftSerial::rx_detect_start);
+ start_bit = 1; // start from second bit
+ rx_bit = 0;
+ rx_error = false;
+}
+
+void MySoftSerial::rx_detect_start(void){
+ int val = rx->read();
+
+ // check start pattern
+ // todo store pattern in array or int
+ bool ok;
+ switch(start_bit){
+ case 0:
+ ok = val==0;
+ break;
+ case 1:
+ ok = val==1;
+ break;
+ case 2:
+ ok = val==0;
+ break;
+ case 3:
+ ok = val==1;
+ rxticker.attach(this, &MySoftSerial::tx_handler);
+ break;
+ default:
+ ok = false;
+ }
+
+ if(ok){
+ rx_bit++;
+ rxticker.setNext(bit_period);
+ } else {
+ // start pattern was not correct, this is not a data packet
+ rxticker.detach();
+ rx->fall(this, &SoftSerial::rx_gpio_irq_handler);
+ }
+}
+
+void MySoftSerial::format(int bits, SoftSerial::Parity parity, int stop_bits) {
+ SoftSerial::format(bits, parity, stop_bits);
+ _total_bits = 4 + _bits + _stop_bits;
+}
+
+void MySoftSerial::tx_handler(void) {
+ if (tx_bit == _total_bits) {
+ tx_bit = -1;
+ // transmission done, start measuring time until next transmission
+ dc_offset_timer.reset();
+ dc_offset_timer.start();
+
+ fpointer[TxIrq].call();
+ return;
+ }
+
+ //Flip output
+ int cur_out = tx->read();
+ tx->write(!cur_out);
+
+ //Calculate when to do it again
+ int count = bit_period;
+ tx_bit++;
+ while(((_char >> tx_bit) & 0x01) == !cur_out) {
+ count+=bit_period;
+ tx_bit++;
+ }
+
+ txticker.setNext(count);
+}