/* * Copyright 2017-2024 Oleg Borodin */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #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(); } }