PaulStoffregen / AltSoftSerial

Software emulated serial using hardware timers for improved compatibility
http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html
328 stars 131 forks source link

parity #5

Open AvengerIl opened 9 years ago

AvengerIl commented 9 years ago

i've found some code of yours online that has a parity implementation. is there any chance you could commit to this repo?

re:http://forum.pjrc.com/threads/24199-AltSoftSerial-amp-parity-e-g-begin%289600-SERIAL_8E1%29

Its impossible to follow that code and make the change myself.

aCaB commented 9 years ago

A small patch against 9cba024f0ba6342a00fda6e1dfa7426f009ad8ad to implement optional TX parity bit. See enum parity_type in AltSoftSerial.h

diff --git a/AltSoftSerial.cpp b/AltSoftSerial.cpp
index 72ff290..5e59f98 100644
--- a/AltSoftSerial.cpp                                                                                                   
+++ b/AltSoftSerial.cpp                                                                                                   
@@ -56,13 +56,14 @@ static volatile uint8_t tx_buffer_head;                                                               
 static volatile uint8_t tx_buffer_tail;                                                                                  
 #define TX_BUFFER_SIZE 68                                                                                                
 static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];                                                                       
-                                                                                                                         
+static enum AltSoftSerial::parity_type tx_parity_flag;                                                                   
+static uint8_t tx_parity_bit;                                                                                            

 #ifndef INPUT_PULLUP                                                                                                     
 #define INPUT_PULLUP INPUT                                                                                               
 #endif                                                                                                                   

-void AltSoftSerial::init(uint32_t cycles_per_bit)                                                                        
+void AltSoftSerial::init(uint32_t cycles_per_bit, enum parity_type parity)                                               
 {                                                                                                                        
        if (cycles_per_bit < 7085) {                                                                                      
                CONFIG_TIMER_NOPRESCALE();                                                                                
@@ -85,6 +86,7 @@ void AltSoftSerial::init(uint32_t cycles_per_bit)                                                       
        tx_state = 0;                                                                                                     
        tx_buffer_head = 0;                                                                                               
        tx_buffer_tail = 0;                                                                                               
+       tx_parity_flag = parity;
        ENABLE_INT_INPUT_CAPTURE();
 }

@@ -119,6 +121,7 @@ void AltSoftSerial::writeByte(uint8_t b)
                tx_state = 1;
                tx_byte = b;
                tx_bit = 0;
+               tx_parity_bit = 0;
                ENABLE_INT_COMPARE_A();
                CONFIG_MATCH_CLEAR();
                SET_COMPARE_A(GET_TIMER_COUNT() + 16);
@@ -138,6 +141,7 @@ ISR(COMPARE_A_INTERRUPT)
        while (state < 9) {
                target += ticks_per_bit;
                bit = byte & 1;
+               tx_parity_bit ^= bit;
                byte >>= 1;
                state++;
                if (bit != tx_bit) {
@@ -154,8 +158,25 @@ ISR(COMPARE_A_INTERRUPT)
                        return;
                }
        }
-       if (state == 9) {
-               tx_state = 10;
+       if(state == 9) {
+               state = tx_state = 10;
+               if(tx_parity_flag != AltSoftSerial::PARITY_NONE) {
+                       if(tx_parity_flag == AltSoftSerial::PARITY_ODD)
+                               tx_parity_bit ^= 1;
+                       else if(tx_parity_flag == AltSoftSerial::PARITY_MARK)
+                               tx_parity_bit = 1;
+                       else if(tx_parity_flag == AltSoftSerial::PARITY_SPACE)
+                               tx_parity_bit = 0;
+                       if(tx_parity_bit)
+                               CONFIG_MATCH_SET();
+                       else
+                               CONFIG_MATCH_CLEAR();
+                       SET_COMPARE_A(target + ticks_per_bit);
+                       return;
+               }
+       }
+       if (state == 10) {
+               tx_state = 11;
                CONFIG_MATCH_SET();
                SET_COMPARE_A(target + ticks_per_bit);
                return;
@@ -172,6 +193,7 @@ ISR(COMPARE_A_INTERRUPT)
                tx_buffer_tail = tail;
                tx_byte = tx_buffer[tail];
                tx_bit = 0;
+               tx_parity_bit = 0;
                CONFIG_MATCH_CLEAR();
                SET_COMPARE_A(target + ticks_per_bit);
                // TODO: how to detect timing_error?
diff --git a/AltSoftSerial.h b/AltSoftSerial.h
index eccb8d8..a616fc0 100644
--- a/AltSoftSerial.h
+++ b/AltSoftSerial.h
@@ -44,7 +44,14 @@ class AltSoftSerial : public Stream
 public:
        AltSoftSerial() { }
        ~AltSoftSerial() { end(); }
-       static void begin(uint32_t baud) { init((ALTSS_BASE_FREQ + baud / 2) / baud); }
+       enum parity_type {
+               PARITY_NONE,
+               PARITY_EVEN,
+               PARITY_ODD,
+               PARITY_MARK,
+               PARITY_SPACE,
+       };
+       static void begin(uint32_t baud, enum parity_type parity = PARITY_NONE) { init((ALTSS_BASE_FREQ + baud / 2) / baud, parity); }
        static void end();
        int peek();
        int read();
@@ -68,7 +75,7 @@ public:
        static void enable_timer0(bool enable) { }
        static bool timing_error;
 private:
-       static void init(uint32_t cycles_per_bit);
+       static void init(uint32_t cycles_per_bit, enum parity_type parity);
        static void writeByte(uint8_t byte);
 };
igittigitt commented 8 years ago

I would REALLY appreciate this! Looking for a Software Serial lib with variable config (Parity- Stop bits) for a long time...

SRGDamia1 commented 6 years ago

Is there any chance this will be added and pulled into the library?

lausdahl commented 5 years ago

I fixed the patch and applied it to the specified git hash in https://github.com/lausdahl/AltSoftSerial/tree/parity I haven't had time to merge it with head of this repo yet.

I tested it with 2400 8E1 which I needed. It works as also described in the original post: https://forum.pjrc.com/threads/24199-AltSoftSerial-amp-parity-e-g-begin%289600-SERIAL_8E1%29

If I get time I might create a pull-request for it.