/* * 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, CC_CMD_SET_WF_FREQ, CC_CMD_SET_WF, CC_CMD_SET_WF_DC, CC_CMD_EN_WF, }; 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, CC_CMD_SET_WF_FREQ_FUNC, CC_CMD_SET_WF_FUNC, CC_CMD_SET_WF_DC_FUNC, CC_CMD_SET_EN_WF_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, CC_CMD_SET_WF_FREQ_DATA_TO_READ, CC_CMD_SET_WF_DATA_TO_READ, CC_CMD_SET_WF_DC_DATA_TO_READ, CC_CMD_SET_EN_WF_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; /*****************************************************************************/ uint32_t read32BitDataFromBuffer(uint8_t pos) { uint32_t tmp = (uint32_t)cc_read_data[pos ] << 24; tmp += (uint32_t)cc_read_data[pos + 1] << 16; tmp += (uint32_t)cc_read_data[pos + 2] << 8; tmp += (uint32_t)cc_read_data[pos + 3]; return tmp; } uint16_t read16BitDataFromBuffer(uint8_t pos) { uint16_t tmp = (uint16_t)cc_read_data[pos ] << 8; tmp += (uint16_t)cc_read_data[pos + 1]; return tmp; } /*****************************************************************************/ void cc_setStartFreq() { uint32_t tmp_start_freq = read32BitDataFromBuffer(0); start_freq = keepFreqRange(tmp_start_freq); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_setEndFreq() { uint32_t tmp_end_freq = read32BitDataFromBuffer(0); end_freq = keepFreqRange(tmp_end_freq); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_setFreqStep() { uint32_t tmp_step_freq = read32BitDataFromBuffer(0); step_freq = keepFreqRange(tmp_step_freq); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_setIntervall() { intervall = read16BitDataFromBuffer(0); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } 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; sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } else { sendSOM(); Serial.write(MSG_TYPE_ANSWER_NOK); sendEOM(); } } void cc_startMeasurement() { // 1. send measurement info to host // MSG_TYPE_CONFIG cc_getConfig(); if (start_freq == 0 || start_freq > 150000000 || end_freq == 0 || end_freq > 150000000 || step_freq == 0 || step_freq > 150000000 || start_freq >= end_freq || intervall == 0) { // on error sendSOM(); Serial.write(MSG_TYPE_ANSWER_NOK); sendEOM(); return; } // 2. start a for loop from the frequence to start to the end frequence 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; // TODO an diesem punkt muss unterschieden werden ob eine waveform ausgegeben werden soll oder eine frequenz, und welche Art von Kurve if (freq < WF_FREQ_MAX_HZ) { setWaveformFrequency(freq); enableWaveformOutput(); pollWaveformGenerator(); // manually poll the waveformgenerator si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 //delay(1); } else { disableWaveformOutput(); 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 sendSOM(); Serial.write(MSG_TYPE_MEAS_FREQ_INFO); send32BitValue(freq); send16BitValue(a0_sum); send16BitValue(a1_sum); sendEOM(); disableWaveformOutput(); 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 sendSOM(); Serial.write(MSG_TYPE_MEAS_END_INFO); sendEOM(); si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0 } void cc_getConfig() { sendSOM(); Serial.write(MSG_TYPE_CONFIG); send32BitValue(start_freq); send32BitValue(end_freq); send32BitValue(step_freq); send16BitValue(intervall); Serial.write((uint8_t)drive_str); sendEOM(); } /*****************************************************************************/ void cc_enableClk(void) { sendSOM(); if (cc_read_data[0] == SI5351_CLK0) { if (start_freq < WF_FREQ_MAX_HZ) // < 8kHz { setWaveformFrequency(start_freq); enableWaveformOutput(); si5351.output_enable(SI5351_CLK0, 0); } else { disableWaveformOutput(); 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); } sendEOM(); } /*****************************************************************************/ void cc_disableClk(void) { sendSOM(); if (cc_read_data[0] == SI5351_CLK0) { disableWaveformOutput(); 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); } sendEOM(); } /*****************************************************************************/ void cc_saveDefaults(void) { writeEEPROMConfig(); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } /*****************************************************************************/ void cc_setClkCorrection(void) { uint32_t tmp_corr = read32BitDataFromBuffer(0); si5351.set_correction(tmp_corr); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_getClkCorrection(void) { uint32_t tmp_corr = si5351.get_correction(); sendSOM(); send32BitValue(tmp_corr); sendEOM(); } void cc_setWFFreq(void) { uint16_t tmp_freq = read16BitDataFromBuffer(0); setWaveformFrequency(tmp_freq); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_setWF(void) { uint8_t tmp_wf = cc_read_data[0]; setWaveform(tmp_wf); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_setWFDC(void) { uint8_t tmp_dc = cc_read_data[0]; setWaveformDC(tmp_dc); sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } void cc_enableWF(void) { uint8_t tmp_en = cc_read_data[0]; if (tmp_en == 0) { disableWaveformOutput(); } else { enableWaveformOutput(); } sendSOM(); Serial.write(MSG_TYPE_ANSWER_OK); sendEOM(); } /*****************************************************************************/ 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 sendSOM(); Serial.write(MSG_TYPE_ANSWER_NOK); sendEOM(); 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; } } /*****************************************************************************/ void sendSOM() { Serial.write(MSG_SOM1); Serial.write(MSG_SOM2); } void sendEOM() { Serial.write(MSG_EOM1); Serial.write(MSG_EOM2); } /*****************************************************************************/ void send32BitValue(uint32_t value) { Serial.write((uint8_t)((value & 0xff000000) >> 24)); Serial.write((uint8_t)((value & 0x00ff0000) >> 16)); Serial.write((uint8_t)((value & 0x0000ff00) >> 8)); Serial.write((uint8_t) (value & 0x000000ff)); } void send16BitValue(uint16_t value) { Serial.write((uint8_t)((value & 0xff00) >> 8)); Serial.write((uint8_t) (value & 0x00ff)); } /*****************************************************************************/