// Measure the offset from the rising edge of the ZCD to the true zero crossing. // An oscilloscope trace of the ZCD pcb, used in the project can be found here: // http://electronics.stackexchange.com/questions/201605/automatic-calibration-of-a-zero-cross-detector-latency // It is evident, that the pulse is wide, but centered around the ZC. // Therefore, we measure its width and divide it by two to get the offset from the rising edge to the true ZC. time_t zcd_calibrate(void) { // Restore interrupt status after exit. // Enable all interrupts here, because there were glitches when altering TIMSK1 form an ISR. char sreg = SREG; sei(); TIMSK1 = (1<<ICIE1); // Enable edge interrupts. // Wait for rising edge of the zcd pulse. g_calibration_mode = true; start_timer1_capture_rising(); while(!g_event_captured); g_event_captured = false; ATOMIC{ TCNT1 = 0; } // Clear timer1. // Measure pulse width. ATOMIC{ start_timer1_capture_falling(); } while(!g_event_captured); volatile time_t count; ATOMIC{ count = ICR1; } // Width of the zcd pulse, in CPU cycles. stop_timer1(); // Estimate offset from measured to real zc. time_t rising_to_zc = count / 2; // In CPU cycles. SREG = sreg; return rising_to_zc; }
/** * \fn void note(char temps, int note) * \brief Permet de jouer une note pendant un certain temps * \param [IN] temps est la duree pendant laquelle on souhaite jouer la note - temps ne doit pas depasser la valeur 11 ( 2^8 / 5760 ) [IN] note est la fréquence d'OCR0A que l'on souhaite jouer */ void note(char temps, int note) { start_timer0(note); start_timer1(temps * 5760); // 100 ms wait_OCR1A_timer1(); stop_timer1(); stop_timer0(); }
uint8_t process_ARE_frame(uint8_t status_code) { uint8_t ack_needed; uint8_t data_size=0; uint8_t command; // LEDs_ToggleLEDs(LED0); // indicate correct frame command=(uint8_t)ARE_frame.request_code; CIM_frame.cim_feature=ARE_frame.cim_feature; CIM_frame.serial_number=ARE_frame.serial_number; CIM_frame.reply_code=(((uint16_t)status_code)<<8) + command; data_size=(uint8_t)ARE_frame.data_size; ack_needed=1; // if ((status_code & (CIM_ERROR_INVALID_ARE_VERSION | CIM_ERROR_CRC_MISMATCH)) == 0) if ((status_code & CIM_ERROR_INVALID_ARE_VERSION) == 0) { // UART_Print(" feature "); UART_Putchar(command); // no serious packet error switch (command) { // process requested command case CMD_REQUEST_FEATURELIST: if (data_size==0) { reply_FeatureList(); // reply requested feature list ack_needed=0; } else status_code |= CIM_ERROR_INVALID_FEATURE; break; case CMD_REQUEST_RESET_CIM: if (data_size!=0) status_code |= CIM_ERROR_INVALID_FEATURE; break; case CMD_REQUEST_START_CIM: if (data_size==0) { cli(); init_CIM_frame(); setupHardware(); start_timer1(); sei(); } else status_code |= CIM_ERROR_INVALID_FEATURE; break; case CMD_REQUEST_STOP_CIM: if (data_size==0) { first_packet=1; // reset first frame indicator etc. stop_timer1(); } else status_code |= CIM_ERROR_INVALID_FEATURE; break; case CMD_REQUEST_READ_FEATURE: // read feature from CIM switch (ARE_frame.cim_feature) { case TEENSY_CIM_FEATURE_UNIQUENUMBER: // read unique serial number if (data_size==0) { reply_UniqueNumber(); ack_needed=0; } else status_code |= CIM_ERROR_INVALID_FEATURE; break; default: // not a valid read feature; status_code |= CIM_ERROR_INVALID_FEATURE; } break; case CMD_REQUEST_WRITE_FEATURE: // write feature to CIM switch (ARE_frame.cim_feature) { // which feature address ? case TEENSY_CIM_FEATURE_MODE_SELECTION: if (data_size==2) { cli(); selection = (uint16_t)ARE_frame.data[0]; selection += ((uint16_t)ARE_frame.data[1])<<8; sei(); } break; case TEENSY_CIM_FEATURE_SET_THRESHOLD: if (data_size==2) { cli(); threshold = (uint16_t)ARE_frame.data[0]; threshold += ((uint16_t)ARE_frame.data[1])<<8; sei(); } break; /*case TEENSY_CIM_FEATURE_SET_ADCPERIOD: if (data_size==2) { cli(); ADC_updatetime= (uint16_t)ARE_frame.data[0]; ADC_updatetime+= ((uint16_t)ARE_frame.data[1])<<8; sei(); } break;*/ default: // not a valid write feature; status_code |= CIM_ERROR_INVALID_FEATURE; } } } if (status_code & CIM_ERROR_INVALID_FEATURE) { // invalid data size or feature // LEDs_ToggleLEDs(LED5); // indicate wrong feature // UART_Print(" invalid data size or no feature "); } if (ack_needed) { reply_Acknowledge(); } return(1); }