SWRMeter/firmware/command_ctrl.ino

431 lines
12 KiB
C++

/*
* Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
* Date: 09/2016
* License: GPLv3
*/
/*****************************************************************************/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <avr/wdt.h>
/*****************************************************************************/
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);
/*****************************************************************************/
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,
};
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,
};
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,
};
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 < 200; t++)
{
uint16_t tmp = analogRead(A0);
tmp = analogRead(A1);
}
uint32_t freq = 0;
for (freq = start_freq; freq < end_freq; freq += step_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 < 20; t++)
{
ta0 += analogRead(A0);
ta1 += analogRead(A1);
}
a0_sum += (ta0 / 20);
a1_sum += (ta1 / 20);
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
}
// 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_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;
}
}
/*****************************************************************************/