/** Configure 16 bit timer to trigger an ISR every second * * Configure "measurement in progress toggle LED-signal" */ void timer1_init(const uint16_t timer1_value) { orig_timer1_count = timer1_value; timer1_count = timer1_value; /** Safeguard: We cannot handle 0 or 1 count measurements. */ if (orig_timer1_count <= 1) { send_text_P(PSTR("Unsupported timer value <= 1")); wdt_soft_reset(); } /* Compare match value into output compare reg. A */ OCR1A = TIMER1_COMPARE_MATCH_VAL; /* Configure and start timer */ TCCR1A = BITF(TIMER1_COMA_MODE, COM1A, 0) | BITF(TIMER1_COMA_MODE, COM1A, 1) | BITF(TIMER1_WGM_MODE, WGM1, 0) | BITF(TIMER1_WGM_MODE, WGM1, 1); TCCR1B = BITF(TIMER1_PRESCALER, CS1, 0) | BITF(TIMER1_PRESCALER, CS1, 1) | BITF(TIMER1_PRESCALER, CS1, 2) | BITF(TIMER1_WGM_MODE, WGM1, 2) | BITF(TIMER1_WGM_MODE, WGM1, 3); /* output compare match A interrupt enable */ TIMSK1 |= _BV(OCIE1A); }
/** Firmware FSM event handler for finished measurement */ inline static firmware_state_t firmware_handle_measurement_finished(const firmware_state_t pstate) { switch (pstate) { case STP_MEASURING: /* end measurement */ cli(); on_measurement_finished(); send_table(PACKET_VALUE_TABLE_DONE); return STP_DONE; break; default: send_text_P(PSTR("invalid state transition")); wdt_soft_reset(); break; } }
/** Firmware FSM event handler for receiving a command packet from the host * * \param pstate current FSM state * \param cmd the command we are to handle * \return new state * * Implicit parameters via global variables: * personality_param_sram[0..sizeof(personality_param_sram)-2] param+token data * personality_param_sram[sizeof(personality_param_sram)-1] size of param+token data */ inline static firmware_state_t firmware_handle_command(const firmware_state_t pstate, const uint8_t cmd) { /* temp vars */ const frame_cmd_t c = (frame_cmd_t)cmd; uprintf("EAT PACKET: %c", cmd); switch (pstate) { case STP_READY: switch (c) { case FRAME_CMD_PERSONALITY_INFO: send_personality_info(); /* fall through */ case FRAME_CMD_ABORT: case FRAME_CMD_INTERMEDIATE: case FRAME_CMD_STATE: send_state_P(PSTR_READY); return STP_READY; break; case FRAME_CMD_PARAMS_TO_EEPROM: /* The param length has already been checked by the frame parser */ send_state_P(PSTR("PARAMS_TO_EEPROM")); eeprom_update_block(&pparam_sram, &pparam_eeprom, sizeof(pparam_eeprom)); send_state_P(PSTR_READY); return STP_READY; break; case FRAME_CMD_PARAMS_FROM_EEPROM: params_copy_from_eeprom_to_sram(); send_eeprom_params_in_sram(); send_state_P(PSTR_READY); return STP_READY; break; case FRAME_CMD_MEASURE: /* The param length has already been checked by the frame parser */ general_personality_start_measurement_sram(); send_state_P(PSTR_MEASURING); return STP_MEASURING; break; case FRAME_CMD_RESET: send_state_P(PSTR_RESET); wdt_soft_reset(); break; } break; case STP_MEASURING: switch (c) { case FRAME_CMD_INTERMEDIATE: /** The value table will be updated asynchronously from ISRs * like ISR(ADC_vect) or ISR(TIMER1_foo), i.e. independent from * this main loop. This will cause glitches in the intermediate * values as the values in the table often consist of more than * a single 8bit machine word. However, we have decided that * for *intermediate* results, those glitches are acceptable. * * Keeping interrupts enabled has the additional advantage that * the measurement continues during send_table(), so we need not * concern ourselves with pausing the measurement timer, or with * making sure we properly reset the hardware which triggered * our ISR within the appropriate time range or anything * similar. * * If you decide to bracket the send_table() call with a * cli()/sei() pair, be aware that you need to solve the issue * of resetting the hardware properly. For example, with the * adc-int-mca personality, you would need to reset the peak * hold capacitor on resume if an event has been detected by the * analog circuit while we had interrupts disabled and thus * ISR(ADC_vect) could not reset the peak hold capacitor. */ send_table(PACKET_VALUE_TABLE_INTERMEDIATE); send_state_P(PSTR_MEASURING); return STP_MEASURING; break; case FRAME_CMD_PERSONALITY_INFO: send_personality_info(); /* fall through */ case FRAME_CMD_PARAMS_TO_EEPROM: case FRAME_CMD_PARAMS_FROM_EEPROM: case FRAME_CMD_MEASURE: case FRAME_CMD_RESET: case FRAME_CMD_STATE: send_state_P(PSTR_MEASURING); return STP_MEASURING; break; case FRAME_CMD_ABORT: send_state_P(PSTR_DONE); cli(); on_measurement_finished(); send_table(PACKET_VALUE_TABLE_ABORTED); send_state_P(PSTR_DONE); return STP_DONE; break; } break; case STP_DONE: switch (c) { case FRAME_CMD_PERSONALITY_INFO: send_personality_info(); /* fall through */ case FRAME_CMD_STATE: send_state_P(PSTR_DONE); return STP_DONE; break; case FRAME_CMD_RESET: send_state_P(PSTR_RESET); wdt_soft_reset(); break; default: send_table(PACKET_VALUE_TABLE_RESEND); send_state_P(PSTR_DONE); return STP_DONE; break; } break; } send_text_P(PSTR("STP_ERROR")); wdt_soft_reset(); }