X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=arducontrol%2Farducontrol.c;h=8ec27eaf7f291e298f8aa76128883c720c6de504;hb=3bbca0dcce53ff9e2cdaa3d39ae18afcbf627f9d;hp=d09fc09c3766e3dca9d41dbbd0125e250dae8c28;hpb=817742862a867673e4cbdb85d274481f7482e1ae;p=model-railway-devices.git diff --git a/arducontrol/arducontrol.c b/arducontrol/arducontrol.c index d09fc09..8ec27ea 100644 --- a/arducontrol/arducontrol.c +++ b/arducontrol/arducontrol.c @@ -11,6 +11,12 @@ Connections for Pololu high-powered motor driver: D2 <-> DIR D3 <-> PWM +Connections for S88 bus: +D4 <-> RESET +D5 <-> LOAD +D6 <-> CLOCK +D7 <-> DATA + ADC connections: ADC0 - current sensor (adjusted for 185 mV/A, centered at Vcc/2) ADC1 - input voltage (adjusted for divisor of 11) @@ -34,361 +40,27 @@ blocks until the operation completes. The command returns as soon as sending its data to the track can start. */ #include -#include "adc.h" -#include "commands.h" -#include "motorola.h" -#include "packet.h" -#include "serial.h" -#include "timer.h" - -Packet packet; -uint8_t out_bit; -uint8_t out_time; -uint8_t out_data; -uint8_t delay_time; - -volatile uint8_t recv_buf[32]; -uint8_t recv_head = 0; -uint8_t recv_tail = 0; -volatile uint8_t recv_fill = 0; -volatile uint8_t recv_overrun = 0; -uint8_t cmd_buf[15]; -uint8_t cmd_length; - -uint16_t track_current_samples[16] = { 0 }; -uint8_t track_current_head = 0; -volatile uint16_t track_current_sum = 0; -uint16_t overcurrent_limit = 1000<<4; -uint8_t overcurrent_sent = 0; - -uint16_t input_voltage_samples[16] = { 0 }; -uint8_t input_voltage_head = 0; -volatile uint16_t input_voltage_sum = 0; - -volatile uint8_t adc_state = 0; +#include +#include "interface.h" +#include "monitor.h" +#include "output.h" +#include "s88.h" -void process_commands(); -uint8_t process_command(); - -int main() +int main(void) { - DDRD = 0x0E; - PORTD = 0; - - serial_init(9600); - timer_start_hz(0, 80000, 1); - adc_init(); + output_init(); + interface_init(); + monitor_init(); + s88_init(); sei(); while(1) { - if(recv_overrun) - { - serial_write(0xFE); - serial_write(RECEIVE_OVERRUN); - recv_overrun = 0; - } - if(recv_fill>0) - process_commands(); - if(!(adc_state&1)) - { - ++adc_state; - adc_read_async(adc_state>>1); - } - if(track_current_sum>overcurrent_limit) - { - PORTD &= ~0x08; - if(!overcurrent_sent) - { - overcurrent_sent = 1; - serial_write(0xFE); - serial_write(OVERCURRENT); - } - } - else - overcurrent_sent = 0; + interface_check(); + monitor_check(); + s88_check(); } return 0; } - -static inline void receive(uint8_t c) -{ - if(recv_fill>=sizeof(recv_buf)) - { - recv_overrun = 1; - return; - } - - recv_buf[recv_head++] = c; - if(recv_head>=sizeof(recv_buf)) - recv_head = 0; - ++recv_fill; -} - -SERIAL_SET_CALLBACK(receive) - -void process_commands() -{ - while(recv_fill>0) - { - uint8_t consumed; - uint8_t c = recv_buf[recv_tail]; - - cmd_length = 0; - - if(c>=0xF0) - { - cmd_length = ~c; - if(recv_fill<=cmd_length) - break; - - uint8_t i, j; - for(i=0, j=recv_tail+1; i=sizeof(recv_buf)) - j = 0; - cmd_buf[i] = recv_buf[j]; - } - - consumed = 1+cmd_length; - } - else - { - serial_write(0xFE); - serial_write(FRAMING_ERROR); - consumed = 1; - } - - recv_tail += consumed; - if(recv_tail>=sizeof(recv_buf)) - recv_tail -= sizeof(recv_buf); - recv_fill -= consumed; - - if(cmd_length>0) - { - uint8_t result = process_command(); - serial_write(0xFE); - serial_write(result); - } - } -} - -uint8_t process_command() -{ - if(cmd_buf[0]==POWER_ON || cmd_buf[0]==POWER_OFF) - { - if(cmd_length!=1) - return LENGTH_ERROR; - - if(cmd_buf[0]==POWER_ON) - PORTD |= 0x08; - else - PORTD &= ~0x08; - } - else if(cmd_buf[0]==READ_TRACK_CURRENT) - { - if(cmd_length!=1) - return LENGTH_ERROR; - - serial_write(0xFC); - serial_write(TRACK_CURRENT); - uint16_t value = track_current_sum>>4; - serial_write(value>>8); - serial_write(value); - } - else if(cmd_buf[0]==SET_OVERCURRENT_LIMIT) - { - if(cmd_length!=3) - return LENGTH_ERROR; - - if(cmd_buf[1]&0xF0) - return INVALID_VALUE; - - overcurrent_limit = (cmd_buf[1]<<12) | (cmd_buf[2]<<4); - } - else if(cmd_buf[0]==READ_INPUT_VOLTAGE) - { - if(cmd_length!=1) - return LENGTH_ERROR; - - serial_write(0xFC); - serial_write(INPUT_VOLTAGE); - uint16_t value = (input_voltage_sum>>3)*5; - serial_write(value>>8); - serial_write(value); - } - else if(cmd_buf[0]==MOTOROLA_SPEED || cmd_buf[0]==MOTOROLA_SPEED_DIRECTION || cmd_buf[0]==MOTOROLA_SPEED_FUNCTION) - { - if(cmd_length!=4) - return LENGTH_ERROR; - - uint8_t addr = cmd_buf[1]; - if(addr>80) - return INVALID_VALUE; - - if(cmd_buf[2]&0x0E) - return INVALID_VALUE; - uint8_t aux = cmd_buf[2]&0x01; - - uint8_t func = (cmd_buf[2]&0xF0)>>4; - if(cmd_buf[0]==MOTOROLA_SPEED_FUNCTION) - { - if(func<1 || func>4) - return INVALID_VALUE; - } - else if(cmd_buf[2]&0xFE) - return INVALID_VALUE; - uint8_t state = cmd_buf[2]&0x02; - - uint8_t speed = cmd_buf[3]&0x7F; - if(speed>14) - return INVALID_VALUE; - - uint8_t dir = !(cmd_buf[3]&0x80); - - while(packet.ready && !packet.done) ; - - if(cmd_buf[0]==MOTOROLA_SPEED) - motorola_locomotive_speed_packet(addr, aux, speed); - else if(cmd_buf[0]==MOTOROLA_SPEED_DIRECTION) - motorola_locomotive_speed_direction_packet(addr, aux, speed, dir); - else if(cmd_buf[0]==MOTOROLA_SPEED_FUNCTION) - motorola_locomotive_speed_function_packet(addr, aux, speed, func, state); - } - else if(cmd_buf[0]==MOTOROLA_REVERSE) - { - if(cmd_length!=3) - return LENGTH_ERROR; - - uint8_t addr = cmd_buf[1]; - if(addr>80) - return INVALID_VALUE; - - if(cmd_buf[2]&0xFE) - return INVALID_VALUE; - uint8_t aux = cmd_buf[2]&0x01; - - while(packet.ready && !packet.done) ; - - motorola_locomotive_reverse_packet(addr, aux); - } - else if(cmd_buf[0]==MOTOROLA_SOLENOID) - { - if(cmd_length!=3) - return LENGTH_ERROR; - - uint8_t addr = cmd_buf[1]; - if(addr>80) - return INVALID_VALUE; - - if(cmd_buf[2]&0x8E) - return INVALID_VALUE; - uint8_t output = (cmd_buf[2]&0x70)>>4; - uint8_t state = cmd_buf[2]&1; - - while(packet.ready && !packet.done) ; - - motorola_solenoid_packet(addr, output, state); - } - else - return INVALID_COMMAND; - - return COMMAND_OK; -} - -static inline void tick() -{ - if(delay_time && --delay_time) - return; - - if(out_time && !--out_time) - { - ++out_bit; - if(out_bit>=packet.length) - { - PORTD &= ~0x04; - if(packet.repeat_count>1) - { - if(packet.repeat_count<0xFF) - --packet.repeat_count; - delay_time = packet.repeat_delay; - packet.sending = 0; - } - else - { - delay_time = packet.final_delay; - packet.done = 1; - } - } - else - { - if((out_bit&7)==0) - out_data = packet.data[out_bit>>3]; - else - out_data >>= 1; - - if(out_data&1) - PORTD |= 0x04; - else - PORTD &= ~0x04; - - out_time = packet.bit_duration; - } - - return; - } - - if(packet.ready && !packet.sending) - { - packet.sending = 1; - out_bit = 0; - out_time = packet.bit_duration; - out_data = packet.data[0]; - if(out_data&1) - PORTD |= 0x04; - else - PORTD &= ~0x04; - } -} - -TIMER_SET_CALLBACK(0, tick) - -static inline void adc_complete(uint16_t value) -{ - if(adc_state==1) - { - // Convert to milliamps: (v*5/1024-2.5)*1000/0.185 - if(value<512) // Ignore negative current readings - value = 0; - else if(value>663) // Limit range so averaging won't overflow - value = 4000; - else - value = (value-512)*132/5; - - uint8_t i = track_current_head; - track_current_sum -= track_current_samples[i]; - track_current_samples[i] = value; - track_current_sum += value; - track_current_head = (i+1)&15; - } - else if(adc_state==3) - { - // Convert to centivolts: (v*5/1024)*100*11 - if(value>744) // Limit range so averaging won't overflow - value = 4000; - else - value = value*43/8; - - uint8_t i = input_voltage_head; - input_voltage_sum -= input_voltage_samples[i]; - input_voltage_samples[i] = value; - input_voltage_sum += value; - input_voltage_head = (i+1)&15; - } - - ++adc_state; -} - -ADC_SET_CALLBACK(adc_complete)