#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)
#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;
#if MB_N_HOLD_REGS_EEPROM > 0
static uint16_t hold_regs_ee[MB_N_HOLD_REGS_EEPROM] EEMEM = {
- 42,
- 0, 0, 0, 30, 30, 30, 30, 0, 0, 0, 0, 30,
- (1 << 4) | (1 << 11), // LED 1
- 0, // LED 2
+ 99,
+ //0 1 2 3 4 5 6 7 8 9 10 11
+ //1 2 3 4 5 6 7 8 9 10 11 12
+ 220, 220, 220, 220, 220, 220, 220, 220, 220, 220, 0, 0,
+ 0x3E0, // LED 1
+ 0x01F, // LED 2
};
#endif
if (transmitting)
return 0;
- if (buf_len == 0) // nothing received yet
- return 0;
-
if (get_clock() - last_rx < REQ_TIMEOUT) // still receiving
return 0;
- if (buf_len < 4) { // too short
- buf_len = 0;
- 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 0;
}
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)
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)
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 {