X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=arducontrol%2Fmonitor.c;fp=arducontrol%2Fmonitor.c;h=c88a0717e1106dcc9d8e6d3d881e69ee87947ce0;hb=b47b38e9dd282c5f8fb1ded25ade805e64d0cf1a;hp=0000000000000000000000000000000000000000;hpb=817742862a867673e4cbdb85d274481f7482e1ae;p=model-railway-devices.git diff --git a/arducontrol/monitor.c b/arducontrol/monitor.c new file mode 100644 index 0000000..c88a071 --- /dev/null +++ b/arducontrol/monitor.c @@ -0,0 +1,122 @@ +#include "adc.h" +#include "interface.h" +#include "monitor.h" +#include "output.h" +#include "serial.h" + +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; + +void monitor_init() +{ + adc_init(); +} + +void monitor_check() +{ + if(!(adc_state&1)) + { + ++adc_state; + adc_read_async(adc_state>>1); + } + + if(track_current_sum>overcurrent_limit) + { + output_set_power(0); + if(!overcurrent_sent) + { + overcurrent_sent = 1; + serial_write(0xFE); + serial_write(OVERCURRENT); + } + } + else + overcurrent_sent = 0; +} + +uint8_t monitor_command() +{ + 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 + return INVALID_COMMAND; + + return COMMAND_OK; +} + +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)