/* * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de * Date: 09/2016 * License: GPLv3 */ /*****************************************************************************/ #include #include #include #include /*****************************************************************************/ void cc_init(void); void cc_abort(void); void cc_processData(uint8_t); void cc_clearReadDataBuffer(void); /*****************************************************************************/ void cc_setStartFreq(void); void cc_setEndFreq(void); void cc_setIntervall(void); void cc_setFreqStep(void); void cc_setDriveStrength(void); void cc_startMeasurement(void); void cc_getConfig(void); void cc_enableClk(void); void cc_disableClk(void); void cc_saveDefaults(void); void cc_setClkCorrection(void); void cc_getClkCorrection(void); /*****************************************************************************/ extern "C" { #include "globals.h" } /*****************************************************************************/ uint8_t cc_commands[] = { CC_CMD_SET_START_FREQ, CC_CMD_SET_END_FREQ, CC_CMD_SET_INTERVALL, CC_CMD_SET_DRIVE_STRENGTH, CC_CMD_SET_FREQ_STEP, CC_CMD_START_MEASUREMENT, CC_CMD_GET_CONFIG, CC_CMD_EN_CLK, CC_CMD_DIS_CLK, CC_CMD_SAV_DFLT, CC_CMD_SET_CLK_CORR, CC_CMD_GET_CLK_CORR, }; void (*cc_cmd_functions[])() = { CC_CMD_SET_START_FREQ_FUNC, CC_CMD_SET_END_FREQ_FUNC, CC_CMD_SET_INTERVALL_FUNC, CC_CMD_SET_DRIVE_STRENGTH_FUNC, CC_CMD_SET_FREQ_STEP_FUNC, CC_CMD_START_MEASUREMENT_FUNC, CC_CMD_GET_CONFIG_FUNC, CC_CMD_EN_CLK_FUNC, CC_CMD_DIS_CLK_FUNC, CC_CMD_SAV_DFLT_FUNC, CC_CMD_SET_CLK_CORR_FUNC, CC_CMD_GET_CLK_CORR_FUNC, }; uint8_t cc_cmd_data_to_read[] = { CC_CMD_SET_START_FREQ_DATA_TO_READ, CC_CMD_SET_END_FREQ_DATA_TO_READ, CC_CMD_SET_INTERVALL_DATA_TO_READ, CC_CMD_SET_DRIVE_STRENGTH_DATA_TO_READ, CC_CMD_SET_FREQ_STEP_DATA_TO_READ, CC_CMD_START_MEASUREMENT_DATA_TO_READ, CC_CMD_GET_CONFIG_DATA_TO_READ, CC_CMD_EN_CLK_DATA_TO_READ, CC_CMD_DIS_CLK_DATA_TO_READ, CC_CMD_SAV_DFLT_DATA_TO_READ, CC_CMD_SET_CLK_CORR_DATA_TO_READ, CC_CMD_GET_CLK_CORR_DATA_TO_READ, }; uint8_t cc_read_data[CC_READ_DATA_MAX]; /*****************************************************************************/ uint8_t cc_state = CC_STATE_READ_SOM1; uint8_t cc_cmd_to_call = CC_CMD_NO_CMD; uint8_t cc_cmd_received_correct = MSG_INCOMPLETE; uint8_t cc_cmd_data_read_cnt = 0; /*****************************************************************************/ void cc_setStartFreq() { uint32_t tmp_start_freq = (uint32_t)cc_read_data[0] << 24; tmp_start_freq += (uint32_t)cc_read_data[1] << 16; tmp_start_freq += (uint32_t)cc_read_data[2] << 8; tmp_start_freq += (uint32_t)cc_read_data[3]; if (tmp_start_freq < 1) tmp_start_freq = 1; if (tmp_start_freq > 150000000) tmp_start_freq = 150000000; start_freq = tmp_start_freq; char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } void cc_setEndFreq() { uint32_t tmp_end_freq = (uint32_t)cc_read_data[0] << 24; tmp_end_freq += (uint32_t)cc_read_data[1] << 16; tmp_end_freq += (uint32_t)cc_read_data[2] << 8; tmp_end_freq += (uint32_t)cc_read_data[3]; if (tmp_end_freq < 1) tmp_end_freq = 1; if (tmp_end_freq > 150000000) tmp_end_freq = 150000000; end_freq = tmp_end_freq; char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } void cc_setFreqStep() { uint32_t tmp_step_freq = (uint32_t)cc_read_data[0] << 24; tmp_step_freq += (uint32_t)cc_read_data[1] << 16; tmp_step_freq += (uint32_t)cc_read_data[2] << 8; tmp_step_freq += (uint32_t)cc_read_data[3]; if (tmp_step_freq < 1) tmp_step_freq = 1; if (tmp_step_freq > 150000000) tmp_step_freq = 150000000; step_freq = tmp_step_freq; char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } void cc_setIntervall() { uint16_t tmp_intervall = (uint16_t)cc_read_data[0] << 8; tmp_intervall += (uint16_t)cc_read_data[1]; if (tmp_intervall < 1) tmp_intervall = 1; if (tmp_intervall > 150000000) tmp_intervall = 150000000; intervall = tmp_intervall; char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } void cc_setDriveStrength() { enum si5351_drive tmp_ds = (enum si5351_drive)cc_read_data[0]; if (tmp_ds == SI5351_DRIVE_2MA || tmp_ds == SI5351_DRIVE_4MA || tmp_ds == SI5351_DRIVE_6MA || tmp_ds == SI5351_DRIVE_8MA) { drive_str = tmp_ds; char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_OK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } else { char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_NOK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } } void cc_startMeasurement() { // 1. send measurement info to host // MSG_TYPE_CONFIG cc_getConfig(); // 2. start a for loop from the frequence to start to the end frequence if (start_freq > 0 && start_freq <= 150000000 && end_freq > 0 && end_freq <= 150000000 && start_freq < end_freq && intervall > 0 && step_freq > 0) { si5351.drive_strength(SI5351_CLK0, drive_str); // 2 4 6 8ma uint8_t t = 0; for (t = 0; t < 100; t++) { uint16_t tmp = analogRead(A0); tmp = analogRead(A1); } uint32_t freq = 0; for (freq = start_freq; freq <= end_freq; freq += step_freq) { if (freq > end_freq) { // prevent to step over the end frequency // maybe the user is not allowed to send data in the frequency band freq = end_freq; } uint32_t a0_sum = 0; uint32_t a1_sum = 0; uint16_t i = 0; si5351.set_freq((uint64_t)freq * 100, SI5351_PLL_FIXED, SI5351_CLK0); si5351.output_enable(SI5351_CLK0, 1); // enable clock output 0 delay(1); for (i = 0; i < intervall; i++) { // 3. on every loop read the analog input A0 and A1 for the in intervall (milliseconds) // and generate the average value, read the ADC value every milli second. uint8_t t = 0; uint16_t ta0 = 0; uint16_t ta1 = 0; for (t = 0; t < MEAS_LOOP_CNT; t++) { ta0 += analogRead(A0); ta1 += analogRead(A1); } a0_sum += (ta0 / MEAS_LOOP_CNT); a1_sum += (ta1 / MEAS_LOOP_CNT); delay(1); } a0_sum = a0_sum / intervall; a1_sum = a1_sum / intervall; // 4. send the current output frequency, the drive strength and the measured ADC values from A0 and A1 to the host // MSG_TYPE_MEAS_FREQ_INFO Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); Serial.write(MSG_TYPE_MEAS_FREQ_INFO); Serial.write((uint8_t)((freq & 0xff000000) >> 24)); Serial.write((uint8_t)((freq & 0x00ff0000) >> 16)); Serial.write((uint8_t)((freq & 0x0000ff00) >> 8)); Serial.write((uint8_t) (freq & 0x000000ff)); Serial.write((uint8_t)((a0_sum & 0xff00) >> 8)); Serial.write((uint8_t) (a0_sum & 0x00ff)); Serial.write((uint8_t)((a1_sum & 0xff00) >> 8)); Serial.write((uint8_t) (a1_sum & 0x00ff)); Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 if (freq >= end_freq) break; // abort the loop because all is done } // 5. send a measurement end message to the host // MSG_TYPE_MEAS_END_INFO char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_MEAS_END_INFO, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } else { // on error char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_NOK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); } si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 } void cc_getConfig() { Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); Serial.write(MSG_TYPE_CONFIG); Serial.write((uint8_t)((start_freq & 0xff000000) >> 24)); Serial.write((uint8_t)((start_freq & 0x00ff0000) >> 16)); Serial.write((uint8_t)((start_freq & 0x0000ff00) >> 8)); Serial.write((uint8_t) (start_freq & 0x000000ff)); Serial.write((uint8_t)((end_freq & 0xff000000) >> 24)); Serial.write((uint8_t)((end_freq & 0x00ff0000) >> 16)); Serial.write((uint8_t)((end_freq & 0x0000ff00) >> 8)); Serial.write((uint8_t) (end_freq & 0x000000ff)); Serial.write((uint8_t)((step_freq & 0xff000000) >> 24)); Serial.write((uint8_t)((step_freq & 0x00ff0000) >> 16)); Serial.write((uint8_t)((step_freq & 0x0000ff00) >> 8)); Serial.write((uint8_t) (step_freq & 0x000000ff)); Serial.write((uint8_t)((intervall & 0xff00) >> 8)); Serial.write((uint8_t) (intervall & 0x00ff)); Serial.write((uint8_t) drive_str); Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } /*****************************************************************************/ void cc_enableClk(void) { Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); if (cc_read_data[0] == SI5351_CLK0) { si5351.set_freq((uint64_t)start_freq * 100, SI5351_PLL_FIXED, SI5351_CLK0); si5351.output_enable(SI5351_CLK0, 1); // enable clock output 0 Serial.write(MSG_TYPE_ANSWER_OK); } else if (cc_read_data[0] == SI5351_CLK1) { si5351.set_freq((uint64_t)start_freq * 100, SI5351_PLL_FIXED, SI5351_CLK1); si5351.output_enable(SI5351_CLK1, 1); // enable clock output 1 Serial.write(MSG_TYPE_ANSWER_OK); } else if (cc_read_data[0] == SI5351_CLK2) { si5351.set_freq((uint64_t)start_freq * 100, SI5351_PLL_FIXED, SI5351_CLK2); si5351.output_enable(SI5351_CLK2, 1); // enable clock output 2 Serial.write(MSG_TYPE_ANSWER_OK); } else { Serial.write(MSG_TYPE_ANSWER_NOK); } Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } /*****************************************************************************/ void cc_disableClk(void) { Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); if (cc_read_data[0] == SI5351_CLK0) { si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 Serial.write(MSG_TYPE_ANSWER_OK); } else if (cc_read_data[0] == SI5351_CLK1) { si5351.output_enable(SI5351_CLK1, 0); // disable clock output 1 Serial.write(MSG_TYPE_ANSWER_OK); } else if (cc_read_data[0] == SI5351_CLK2) { si5351.output_enable(SI5351_CLK2, 0); // disable clock output 2 Serial.write(MSG_TYPE_ANSWER_OK); } else { Serial.write(MSG_TYPE_ANSWER_NOK); } Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } /*****************************************************************************/ void cc_saveDefaults(void) { writeEEPROMConfig(); Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); Serial.write(MSG_TYPE_ANSWER_OK); Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } /*****************************************************************************/ void cc_setClkCorrection(void) { uint32_t tmp_corr = (uint32_t)cc_read_data[0] << 24; tmp_corr += (uint32_t)cc_read_data[1] << 16; tmp_corr += (uint32_t)cc_read_data[2] << 8; tmp_corr += (uint32_t)cc_read_data[3]; si5351.set_correction(tmp_corr); Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); Serial.write(MSG_TYPE_ANSWER_OK); Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } void cc_getClkCorrection(void) { uint32_t tmp_corr = si5351.get_correction(); Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); Serial.write((uint8_t)((tmp_corr & 0xff000000) >> 24)); Serial.write((uint8_t)((tmp_corr & 0x00ff0000) >> 16)); Serial.write((uint8_t)((tmp_corr & 0x0000ff00) >> 8)); Serial.write((uint8_t) (tmp_corr & 0x000000ff)); Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } /*****************************************************************************/ void cc_init() { cc_state = CC_STATE_READ_SOM1; cc_cmd_to_call = CC_CMD_NO_CMD; cc_cmd_data_read_cnt = 0; cc_cmd_received_correct = MSG_INCOMPLETE; } /*****************************************************************************/ void cc_abort() { // send abort message, then init char* tmp = " "; sprintf(tmp, "%c%c%c%c%c", MSG_SOM1, MSG_SOM2, MSG_TYPE_ANSWER_NOK, MSG_EOM1, MSG_EOM2); Serial.write(tmp); cc_init(); } /*****************************************************************************/ void cc_processData(uint8_t c) { uint8_t i = 0; switch (cc_state) { //*********************************// case CC_STATE_READ_SOM1:; if (c == MSG_SOM1) cc_state = CC_STATE_READ_SOM2; else cc_abort(); break; //*********************************// case CC_STATE_READ_SOM2:; if (c == MSG_SOM2) cc_state = CC_STATE_READ_CMD; else cc_abort(); break; //*********************************// case CC_STATE_READ_CMD:; for (i = 0; i < sizeof(cc_commands)/sizeof(uint8_t); i++) { if (cc_commands[i] == c) { if (cc_cmd_data_to_read[i] > 0) cc_state = CC_STATE_READ_DATA; else cc_state = CC_STATE_READ_EOM1; cc_cmd_to_call = i; // remember the index of command to call break; // break the loop } } break; //*********************************// case CC_STATE_READ_DATA:; // write the variable c to the input buffer cc_read_data[cc_cmd_data_read_cnt] = c; if (cc_cmd_data_read_cnt >= cc_cmd_data_to_read[cc_cmd_to_call]-1) { cc_state = CC_STATE_READ_EOM1; } cc_cmd_data_read_cnt++; break; //*********************************// case CC_STATE_READ_EOM1:; if (c == MSG_EOM1) cc_state = CC_STATE_READ_EOM2; else cc_abort(); break; //*********************************// case CC_STATE_READ_EOM2:; if (c == MSG_EOM2) { cc_cmd_received_correct = MSG_COMPLETE; } else cc_abort(); break; default: cc_abort(); } //*********************************// if (cc_cmd_received_correct == MSG_COMPLETE) { // call the function using the received data (*cc_cmd_functions[cc_cmd_to_call])(); // clear the read buffer cc_clearReadDataBuffer(); cc_init(); } } /*****************************************************************************/ void cc_clearReadDataBuffer() { uint8_t i = 0; for (i = 0; i < CC_READ_DATA_MAX; i++) { cc_read_data[i] = 0x00; } } /*****************************************************************************/