Files
pa50contr/contr.c
Олег Бородин f38727054d update
2024-08-27 11:29:20 +02:00

555 lines
12 KiB
C

/*
* Copyright 2017-2024 Oleg Borodin <onborodin@gmail.com>
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <tool.h>
#include <eeprom.h>
#include <disp.h>
#include <uart.h>
#include <temp.h>
#include <relay.h>
#include <timer.h>
#include <adc.h>
#include <button.h>
#include <temp.h>
#include <contr.h>
#define CONTR_BAND_OFF 0x01
#define CONTR_BAND_10M 0x02
#define CONTR_BAND_20M 0x03
#define CONTR_BAND_40M 0x04
#define CONTR_BAND_80M 0x05
#define CONTR_DELAY_OFF 0
#define CONTR_DELAY_100MS 22
#define CONTR_DELAY_200MS 44
#define CONTR_DELAY_300MS 66
#define CONTR_DELAY_500MS 110
#define CONTR_FREQARR_SIZE 32
#define CONTR_VCCARR_SIZE 4
#define CONTR_PWRARR_SIZE 8
#define CONTR_SWRARR_SIZE 16
#define CONTR_DISPSTR_SIZE 20
#define CONTR_TEMPARR_SIZE 16
#define CONTR_BAND_EEPROM_ADDR 0x00
#define CONTR_TXDELAY_EEPROM_ADDR 0x12
#define CONTR_HIGHT_TEMP 3500
#define CONTR_CRIT_TEMP 5000
#define CONTR_CRIT_VSWR 5000
typedef struct {
uint8_t band;
uint16_t freq;
uint16_t vcc;
uint16_t freq_arr[CONTR_FREQARR_SIZE];
size_t freq_pos;
uint16_t fwd_arr[CONTR_PWRARR_SIZE];
size_t fwd_pos;
uint16_t fwd_awg;
uint16_t rev_arr[CONTR_PWRARR_SIZE];
size_t rev_pos;
uint16_t rev_awg;
uint16_t swr_arr[CONTR_SWRARR_SIZE];
size_t swr_pos;
uint16_t swr_awg;
bool swr_crit;
uint16_t temp_arr[CONTR_TEMPARR_SIZE];
size_t temp_pos;
uint16_t temp_awg;
char disp_str[CONTR_DISPSTR_SIZE];
uint16_t tx_delay;
uint16_t tx_cnt;
bool tx_enable;
bool tx_bypass;
} contr_t;
contr_t contr;
void contr_switch_band(void);
void contr_set_band(uint8_t band);
void contr_write_band(void);
void contr_read_band(void);
char* contr_get_bandname();
void contr_write_txdelay(void);
void contr_read_txdelay(void);
char* contr_get_delayname(void);
void contr_switch_delay(void) ;
void contr_ptt_handle(void);
void contr_tx_handle(void);
void contr_init(void) {
contr.band = CONTR_BAND_OFF;
contr.vcc = 0;
contr.fwd_pos = 0;
contr.fwd_awg = 0;
for (size_t i = 0; i < CONTR_PWRARR_SIZE; i++) {
contr.fwd_arr[i] = 0;
}
contr.rev_pos = 0;
contr.rev_awg = 0;
for (size_t i = 0; i < CONTR_PWRARR_SIZE; i++) {
contr.rev_arr[i] = 0;
}
contr.swr_pos = 0;
contr.swr_awg = 0;
for (size_t i = 0; i < CONTR_SWRARR_SIZE; i++) {
contr.swr_arr[i] = 0;
}
contr.swr_crit = false;
contr.disp_str[0] = '\0';
contr.tx_delay = CONTR_DELAY_200MS;
contr.tx_cnt = 0;
contr.tx_enable = false;
contr.tx_bypass = true;
}
void contr_setup(void) {
contr_read_band();
contr_read_txdelay();
}
#define CONTR_VCC_SCALE 270
void contr_measure_vcc(void) {
contr.vcc = adc_read(ACD_CHANELL3) / CONTR_VCC_SCALE;
}
uint16_t contr_get_vcc(void) {
return contr.vcc;
}
#define CONTR_FWD_SCALE 39
#define CONTR_REV_SCALE 39
void contr_measure_swr(void) {
uint16_t fwd = adc_read(ACD_CHANELL1) / CONTR_FWD_SCALE;
uint16_t rev = adc_read(ACD_CHANELL0) / CONTR_REV_SCALE;
contr.fwd_arr[contr.fwd_pos++] = fwd;
if ((contr.fwd_pos) > CONTR_PWRARR_SIZE) {
contr.fwd_pos = 0;
}
contr.rev_arr[contr.rev_pos++] = rev;
if ((contr.rev_pos) > CONTR_PWRARR_SIZE) {
contr.rev_pos = 0;
}
}
void contr_calc_swr(void) {
uint32_t fwd_awg = 0;
for (size_t i = 0; i < CONTR_PWRARR_SIZE; i++) {
fwd_awg += contr.fwd_arr[i];
}
fwd_awg = (fwd_awg + CONTR_PWRARR_SIZE - 1) / CONTR_PWRARR_SIZE;
contr.fwd_awg = (uint16_t)(fwd_awg);
uint32_t rev_awg = 0;
for (size_t i = 0; i < CONTR_PWRARR_SIZE; i++) {
rev_awg += contr.rev_arr[i];
}
rev_awg = (rev_awg + CONTR_PWRARR_SIZE - 1) / CONTR_PWRARR_SIZE;
contr.rev_awg = (uint16_t)(rev_awg);
uint32_t pwr_diff = (fwd_awg - rev_awg);
uint32_t swr = 0;
if (pwr_diff != 0) {
swr = ((fwd_awg + rev_awg) * 100) / pwr_diff;
}
contr.swr_arr[contr.swr_pos++] = swr;
if ((contr.swr_pos) > CONTR_SWRARR_SIZE) {
contr.swr_pos = 0;
}
uint32_t swr_awg = 0;
for (size_t i = 0; i < CONTR_SWRARR_SIZE; i++) {
swr_awg += contr.swr_arr[i];
}
swr_awg /= CONTR_SWRARR_SIZE;
contr.swr_awg = (uint16_t)(swr_awg * 10);
}
uint16_t contr_get_fwd(void) {
return contr.fwd_awg;
}
uint16_t contr_get_rev(void) {
return contr.rev_awg;
}
uint16_t contr_get_swr(void) {
return contr.swr_awg;
}
void contr_reset_prot(void) {
contr.swr_crit = false;
}
void contr_switch_txbypass(void) {
if (contr.tx_bypass == true) {
contr.tx_bypass = false;
} else {
contr.tx_bypass = true;
}
}
ISR(TIMER0_OVF_vect) {
button_handle();
contr_measure_vcc();
contr_measure_swr();
contr_ptt_handle();
contr_calc_swr();
uart_handle();
}
#define CONTR_KEY_TXBYPASS 1
#define CONTR_KEY_RSTPROT 2
#define CONTR_KEY_SWDELAY 3
#define CONTR_KEY_SWBAND 4
void contr_button_eval(void) {
switch (button_get()) {
case CONTR_KEY_TXBYPASS:
contr_switch_txbypass();
break;
case CONTR_KEY_RSTPROT:
contr_reset_prot();
break;
case CONTR_KEY_SWDELAY:
contr_switch_delay();
break;
case CONTR_KEY_SWBAND:
contr_switch_band();
break;
}
}
void contr_show_logo(void) {
disp_clear();
char* dispstr = "Made by R2FDX";
disp_string(1, 1, dispstr);
_delay_ms(200);
disp_clear();
}
void contr_show_band(void) {
disp_string(0, 13, contr_get_bandname());
}
void contr_show_vcc(void) {
sprintf(contr.disp_str, "%3.1fv", (float)contr_get_vcc() / 10);
disp_string(3, 11, contr.disp_str);
}
void contr_show_tx(void) {
if (contr.tx_enable) {
disp_string(2, 0, "TX");
} else {
disp_string(2, 0, " ");
}
}
void contr_show_bypass(void) {
if (contr.tx_bypass) {
disp_string(3, 7, "OFF");
} else {
disp_string(3, 7, " ON");
}
}
void contr_show_button(void) {
if (button_is_pressed()) {
disp_string(1, 12, "*");
} else {
disp_string(1, 12, " ");
}
if (button_was_pressed()) {
sprintf(contr.disp_str, "%u", button.push_counter);
disp_string(1, 13, contr.disp_str);
} else {
disp_string(1, 13, " ");
}
}
void contr_show_delay(void) {
disp_string(0, 0, contr_get_delayname());
}
void contr_show_fwd(void) {
sprintf(contr.disp_str, "F=%4.1f", (float)contr_get_fwd() / 100.0F);
disp_string(1, 0, contr.disp_str);
}
void contr_show_rev(void) {
sprintf(contr.disp_str, "R=%4.1f", (float)contr_get_rev() / 100.F);
disp_string(1, 8, contr.disp_str);
}
void contr_show_swr(void) {
if (contr.swr_crit) {
sprintf(contr.disp_str, "%4.2f! ", (float)contr_get_swr() * 0.001F);
} else {
sprintf(contr.disp_str, "%4.2f ", (float)contr_get_swr() * 0.001F);
}
disp_string(2, 6, contr.disp_str);
}
void contr_measure_temp(void) {
uint16_t temp = ds18b20_get_temp();
contr.temp_arr[contr.temp_pos++] = temp;
if ((contr.temp_pos) > CONTR_TEMPARR_SIZE) {
contr.temp_pos = 0;
}
uint32_t temp_awg = 0;
for (size_t i = 0; i < CONTR_TEMPARR_SIZE; i++) {
temp_awg += contr.temp_arr[i];
}
temp_awg = (temp_awg + CONTR_TEMPARR_SIZE - 1) / CONTR_TEMPARR_SIZE;
contr.temp_awg = (uint16_t)(temp_awg);
}
void contr_show_temp(void) {
if (fan_is_on()) {
sprintf(contr.disp_str, "%2.1fc* ", (float)contr.temp_awg * 0.01F);
} else {
sprintf(contr.disp_str, "%2.1fc ", (float)contr.temp_awg * 0.01F);
}
disp_string(3, 0, contr.disp_str);
}
void contr_temp_handle(void) {
if (contr.temp_awg > CONTR_HIGHT_TEMP) {
fan_on();
} else {
fan_off();
}
}
void contr_write_band(void) {
eeprom_write_bytes(CONTR_BAND_EEPROM_ADDR, &contr.band, sizeof(contr.band));
}
void contr_read_band(void) {
eeprom_read_bytes(CONTR_BAND_EEPROM_ADDR, &contr.band, sizeof(contr.band));
}
void contr_switch_band(void) {
switch (contr.band) {
case CONTR_BAND_10M:
contr_set_band(CONTR_BAND_20M);
break;
case CONTR_BAND_20M:
contr_set_band(CONTR_BAND_40M);
break;
case CONTR_BAND_40M:
contr_set_band(CONTR_BAND_80M);
break;
case CONTR_BAND_80M:
contr_set_band(CONTR_BAND_10M);
break;
case CONTR_BAND_OFF:
contr_set_band(CONTR_BAND_10M);
break;
default:
contr_set_band(CONTR_BAND_OFF);
break;
}
}
void contr_set_band(uint8_t band) {
ampl_off();
_delay_ms(10);
contr.band = band;
switch (contr.band) {
case CONTR_BAND_10M:
filter80m_off();
filter40m_off();
filter20m_off();
filter10m_on();
break;
case CONTR_BAND_20M:
filter80m_off();
filter40m_off();
filter10m_off();
filter20m_on();
break;
case CONTR_BAND_40M:
filter80m_off();
filter20m_off();
filter10m_off();
filter40m_on();
break;
case CONTR_BAND_80M:
filter40m_off();
filter20m_off();
filter10m_off();
filter80m_on();
break;
default:
break;
}
contr_write_band();
atten_off();
_delay_ms(10);
}
char* contr_get_bandname() {
char* bandstr = NULL;
switch (contr.band) {
case CONTR_BAND_10M:
bandstr = "10m";
break;
case CONTR_BAND_20M:
bandstr = "20m";
break;
case CONTR_BAND_40M:
bandstr = "40m";
break;
case CONTR_BAND_80M:
bandstr = "80m";
break;
case CONTR_BAND_OFF:
bandstr = "OFF";
break;
default:
bandstr = "UNK";
break;
}
return bandstr;
}
void contr_ptt_handle(void) {
if (contr.tx_bypass) {
if (contr.swr_awg > CONTR_CRIT_VSWR) {
contr.swr_crit = true;
contr.tx_enable = false;
ampl_off();
}
return;
}
if (ptt_is_pressed() && !contr.swr_crit) {
if (contr.swr_awg > CONTR_CRIT_VSWR) {
contr.swr_crit = true;
contr.tx_enable = false;
ampl_off();
return;
}
contr.tx_cnt = contr.tx_delay;
contr.tx_enable = true;
}
if (contr.tx_cnt > 0) {
contr.tx_cnt--;
} else if (contr.tx_cnt == 0) {
contr.tx_enable = false;
}
}
void contr_tx_handle(void) {
if (contr.tx_enable && !contr.swr_crit) {
buzzer_on();
} else {
buzzer_off();
}
}
void contr_write_txdelay(void) {
eeprom_write_bytes(CONTR_TXDELAY_EEPROM_ADDR, (uint8_t*)(&contr.tx_delay), sizeof(contr.tx_delay));
}
void contr_read_txdelay(void) {
eeprom_read_bytes(CONTR_TXDELAY_EEPROM_ADDR, (uint8_t*)(&contr.tx_delay), sizeof(contr.tx_delay));
}
void contr_switch_delay(void) {
switch (contr.tx_delay) {
case CONTR_DELAY_100MS:
contr.tx_delay = CONTR_DELAY_200MS;
break;
case CONTR_DELAY_200MS:
contr.tx_delay = CONTR_DELAY_300MS;
break;
case CONTR_DELAY_300MS:
contr.tx_delay = CONTR_DELAY_500MS;
break;
case CONTR_DELAY_500MS:
contr.tx_delay = CONTR_DELAY_100MS;
break;
default:
contr.tx_delay = CONTR_DELAY_200MS;
break;
}
contr_write_txdelay();
}
char* contr_get_delayname(void) {
switch (contr.tx_delay) {
case CONTR_DELAY_100MS:
return "100ms";
break;
case CONTR_DELAY_200MS:
return "200ms";
break;
case CONTR_DELAY_300MS:
return "300ms";
break;
case CONTR_DELAY_500MS:
return "500ms";
break;
default:
break;
}
return " ?ms";
}
void contr_main(void) {
contr_show_logo();
uint16_t counter = 0;
while (true) {
contr_ptt_handle();
contr_show_button();
contr_show_tx();
contr_show_delay();
contr_button_eval();
contr_show_vcc();
contr_show_swr();
contr_show_bypass();
contr_show_band();
contr_measure_temp();
contr_show_temp();
contr_temp_handle();
contr_tx_handle();
counter++;
_delay_ms(1);
//if ((counter % 10) == 1) buzzer_onoff();
}
}