]> www.fi.muni.cz Git - openparking.git/blobdiff - firmware/modbus.c
error counters to modbus
[openparking.git] / firmware / modbus.c
index 4e8456354e1a5385d630eb7f4cd59cff0f6606a3..c895c5f30ec71336e08a4820b059b9cfec22f827 100644 (file)
@@ -14,7 +14,7 @@
 #include "clock.h"
 #include "modbus.h"
 
-#define BUFSIZE 128 // maximum request size
+#define BUFSIZE 180 // maximum request size
 
 // configure the control pin
 #define ctl_pin_setup()        do { DDRD  |=  _BV(PD2); } while (0)
@@ -28,7 +28,7 @@ typedef uint8_t  bufptr_t;
 #endif
 
 static volatile bufptr_t buf_len, tx_ptr;
-static volatile uint8_t buffer[BUFSIZE], transmitting;;
+static volatile uint8_t buffer[BUFSIZE], transmitting;
 static volatile uint16_t last_rx;
 #ifndef mb_unit_id
 static uint8_t mb_unit_id;
@@ -159,7 +159,7 @@ static mb_exception write_single_reg(uint16_t reg, uint16_t val)
        return MB_OK;
 }
 
-void modbus_poll()
+uint8_t modbus_poll()
 {
        bufptr_t packet_len;
        uint16_t crc;
@@ -167,22 +167,14 @@ void modbus_poll()
 
        ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
                if (transmitting)
-                       return;
-
-               if (buf_len == 0) // nothing received yet
-                       return;
+                       return 0;
 
                if (get_clock() - last_rx < REQ_TIMEOUT) // still receiving
-                       return;
-
-               if (buf_len < 4) { // too short
-                       buf_len = 0;
-                       return;
-               }
+                       return 0;
 
-               if (buffer[0] != mb_unit_id) { // not for myself
+               if (buf_len < 4) { // too short (or not for us)
                        buf_len = 0;
-                       return;
+                       return 0;
                }
 
                transmitting = 1; // disable further reads
@@ -197,7 +189,7 @@ void modbus_poll()
                        transmitting = 0;
                        buf_len = 0;
                }
-               return;
+               return 1;
        }
 
        packet_len -= 2; // strip the CRC
@@ -207,14 +199,14 @@ void modbus_poll()
 
        switch (buffer[1]) { // function
        case 3:
-               if (packet_len == 5)
+               if (packet_len == 6)
                        rv = read_holding_regs(
                                get_word(buffer, 2),
                                get_word(buffer, 4)
                        );
                break;
        case 6:
-               if (packet_len == 5)
+               if (packet_len == 6)
                        rv = write_single_reg(
                                get_word(buffer, 2),
                                get_word(buffer, 4)
@@ -234,21 +226,35 @@ void modbus_poll()
        tx_ptr = 0;
        ctl_pin_on();
        UCSR0B |= _BV(UDRIE0);
+
+       return 1;
 }
 
 ISR(USART_RX_vect)
 {
        uint8_t rx_byte = UDR0;
+       clock_t now = get_clock();
+
+       if (transmitting) // how did we get here? discard it
+               goto out;
 
-       if (transmitting) // discard it
-               return;
+       if (buf_len && buffer[0] != mb_unit_id) // not for us
+               goto out;
 
-       buffer[buf_len] = rx_byte;
+       if (buf_len == BUFSIZE) { // overrun - discard the packet
+               buffer[0] = 0xFF;
+               buf_len = 1;
+               goto out;
+       }
 
-       if (buf_len + 1 < BUFSIZE) // ignore overruns
-               buf_len++;
+       if (now - last_rx >= REQ_TIMEOUT) { // new packet; start over
+               buf_len = 0;
+       }
 
-       last_rx = get_clock();
+       // TODO: we can probably calculate the CRC here as well
+       buffer[buf_len++] = rx_byte;
+out:
+       last_rx = now;
 }
 
 ISR(USART_TX_vect)
@@ -261,7 +267,8 @@ ISR(USART_TX_vect)
 
 ISR(USART_UDRE_vect)
 {
-       if (tx_ptr+1 >= buf_len) {
+       if (tx_ptr >= buf_len) {
+               UCSR0A |= _BV(TXC0); // clear the pending TXC flag
                UCSR0B |= _BV(TXCIE0); // enable xmit complete irq
                UCSR0B &= ~_BV(UDRIE0); // disable ourselves
        } else {