/* * Copyright 2017 Oleg Borodin */ #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 contr_t contr; void contr_key_init(void); void contr_key_handle(void); void contr_key_reset(void); void contr_switch_band(void); void contr_set_band(uint8_t band); void contr_vcc_measure(void); float contr_vcc_calc(void); void contr_fwd_measure(void); float contr_fwd_calc(void); void contr_rev_measure(void); float contr_rev_calc(void); void contr_write_band(void); void contr_read_band(void); ISR(TIMER0_OVF_vect) { contr_key_handle(); contr_fwd_measure(); contr_rev_measure(); contr_vcc_measure(); volatile uint8_t xchar; while ((xchar = fifo_getc(&uart_outbuf)) > 0) { while (!REG_BIT_ISUP(UCSR0A, UDRE0)); UDR0 = xchar; } } void contr_init(void) { contr.temp = 0.0F; contr.band = CONTR_BAND_OFF; contr.vcc_pos = 0; for (size_t i = 0; i < VCC_SIZE; i++) { contr.vcc[i] = 0; } contr.fwd_pos = 0; for (size_t i = 0; i < FWD_SIZE; i++) { contr.fwd[i] = 0; } contr.rev_pos = 0; for (size_t i = 0; i < REV_SIZE; i++) { contr.rev[i] = 0; } contr.key_was_pressed = false; contr.key_time_counter = 0; contr.key_tap_counter = 0; contr.key_strokes_ended = false; } void contr_setup(void) { contr_read_band(); contr_key_init(); adc_init(); timer0_init(); } void contr_switch_band(void) { relaytx_off(); _delay_ms(100); relay80m_off(); relay40m_off(); relay20m_off(); relay10m_off(); _delay_ms(100); switch (contr.band) { case CONTR_BAND_10M: relay20m_on(); contr.band = CONTR_BAND_20M; break; case CONTR_BAND_20M: relay40m_on(); contr.band = CONTR_BAND_40M; break; case CONTR_BAND_40M: relay80m_on(); contr.band = CONTR_BAND_80M; break; case CONTR_BAND_80M: relay10m_on(); contr.band = CONTR_BAND_10M; break; default: break; } contr_write_band(); _delay_ms(100); atten_on(); _delay_ms(100); } char* contr_get_bandname(uint8_t band) { 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; } return bandstr; } #define CONTR_KEY_SWBAND 2 #define CONTR_KEY_BUZZER 4 #define CONTR_KEY_FUN 5 void contr_key_eval(void) { if (contr.key_strokes_ended) { switch (contr.key_tap_counter) { case CONTR_KEY_SWBAND: contr_key_reset(); contr_switch_band(); break; case CONTR_KEY_BUZZER: contr_key_reset(); buzzer_onoff(); break; case CONTR_KEY_FUN: contr_key_reset(); fan_onoff(); break; default: contr_key_reset(); break; } } } void contr_show_logo(void) { char* dispstr = "Made by R2FDX"; disp_string(1, 1, dispstr); } void contr_temp_measure(void) { contr.temp = ds18b20_get_temp(); } float contr_temp_calc(void) { return contr.temp; } void contr_main(void) { uint16_t counter = 0; char dispstr[17] = { '\0' }; char* bandstr = NULL; disp_clear(); contr_show_logo(); _delay_ms(500); disp_clear(); printf("READY>\n\r# "); while (true) { contr_key_eval(); if (contr.key_tap_counter) { sprintf(dispstr, "%2d", contr.key_tap_counter); disp_string(2, 12, dispstr); } else { sprintf(dispstr, " "); disp_string(2, 12, dispstr); } if ((counter % 64) == 1) { contr_temp_measure(); } if ((counter % 4) == 1) { disp_string(0, 12, contr_get_bandname(contr.band)); sprintf(dispstr, "%3.2fV", contr_vcc_calc()); disp_string(0, 0, dispstr); float fwd = contr_fwd_calc(); sprintf(dispstr, "FWD %3.1fW ", fwd); disp_string(1, 2, dispstr); float rev = contr_rev_calc(); sprintf(dispstr, "REV %3.1fW ", rev); disp_string(2, 2, dispstr); float vswr = 0.0F; if (fwd > 0.1F) { vswr = (fwd + rev) / (fwd - rev); } sprintf(dispstr, "%3.1f ", vswr); disp_string(3, 10, dispstr); sprintf(dispstr, "%3.2fC", contr_temp_calc()); disp_string(3, 0, dispstr); } counter++; _delay_ms(100); } } void contr_vcc_measure(void) { REG_SETUP_BIT(ADMUX, MUX0); REG_SETUP_BIT(ADMUX, MUX1); REG_SETDOWN_BIT(ADMUX, MUX2); REG_SETDOWN_BIT(ADMUX, MUX3); REG_SETUP_BIT(ADCSRA, ADSC); while (ADCSRA & BIT(ADSC)); uint16_t lval = (uint16_t)ADCL; uint16_t hval = (uint16_t)ADCH; hval = (hval << 8) & 0xFF00; lval = lval & 0x00FF; if (++contr.vcc_pos > VCC_SIZE) { contr.vcc_pos = 0; } contr.vcc[contr.vcc_pos] = (hval | lval); } #define CONTR_VCC_SCALE 2673.0F float contr_vcc_calc(void) { uint32_t vcc = 0; uint8_t n = 0; for (size_t i = 0; i < VCC_SIZE; i++) { if (contr.vcc[i]) { n++; vcc += contr.vcc[i]; } } float xvcc = 0.0F; if (n) { vcc /= n; xvcc = (float)vcc / CONTR_VCC_SCALE; } return xvcc; } void contr_fwd_measure(void) { REG_SETUP_BIT(ADMUX, MUX0); REG_SETDOWN_BIT(ADMUX, MUX1); REG_SETDOWN_BIT(ADMUX, MUX2); REG_SETDOWN_BIT(ADMUX, MUX3); REG_SETUP_BIT(ADCSRA, ADSC); while (ADCSRA & BIT(ADSC)); uint16_t lval = (uint16_t)ADCL; uint16_t hval = (uint16_t)ADCH; hval = (hval << 8) & 0xFF00; lval = lval & 0x00FF; if (++contr.fwd_pos > FWD_SIZE) { contr.fwd_pos = 0; } contr.fwd[contr.fwd_pos] = (hval | lval); } float contr_fwd_calc(void) { uint32_t fwd = 0; uint8_t n = 0; for (size_t i = 0; i < FWD_SIZE; i++) { fwd += contr.fwd[i]; } float xfwd = 0.0F; xfwd = (float)fwd / 3760.0F / FWD_SIZE; return xfwd; } void contr_rev_measure(void) { REG_SETDOWN_BIT(ADMUX, MUX0); REG_SETDOWN_BIT(ADMUX, MUX1); REG_SETDOWN_BIT(ADMUX, MUX2); REG_SETDOWN_BIT(ADMUX, MUX3); REG_SETUP_BIT(ADCSRA, ADSC); while (ADCSRA & BIT(ADSC)); uint16_t lval = (uint16_t)ADCL; uint16_t hval = (uint16_t)ADCH; hval = (hval << 8) & 0xFF00; lval = lval & 0x00FF; if (++contr.rev_pos > REV_SIZE) { contr.rev_pos = 0; } contr.rev[contr.rev_pos] = (hval | lval); } float contr_rev_calc(void) { uint32_t rev = 0; for (size_t i = 0; i < REV_SIZE; i++) { rev += contr.rev[i]; } float xrev = 0.0F; xrev = (float)rev / 164.0F / REV_SIZE; return xrev; } void contr_write_band(void) { eeprom_write_bytes(0x00, &contr.band, sizeof(contr.band)); } void contr_read_band(void) { eeprom_read_bytes(0x00, &contr.band, sizeof(contr.band)); } void contr_key_init(void) { /* D3 PD3: Set key input */ REG_SETDOWN_BIT(DDRD, PD3); REG_SETUP_BIT(PORTD, PD3); } bool contr_key_is_pressed(void) { if (REG_BIT_VALUE(PIND, PD3)) { return true; } return false; } #define CONTR_KEY_CNTINPRESS 100 #define CONTR_KEY_CNTRELEASE 100 #define CONTR_KEY_CNTUNTAP_READY 1200 #define CONTR_KEY_CNTUNTAP_CLEAN 4000 void contr_key_handle(void) { if (!contr.key_was_pressed) { if (contr_key_is_pressed()) { contr.key_time_counter++; contr.key_time_untap++; } if (contr.key_time_counter > CONTR_KEY_CNTINPRESS) { contr.key_time_counter = 0; contr.key_was_pressed = true; } } else { if (!contr_key_is_pressed()) { contr.key_time_counter++; } if (contr.key_time_counter > CONTR_KEY_CNTRELEASE) { contr.key_time_counter = 0; contr.key_was_pressed = false; contr.key_tap_counter++; contr.key_time_untap = 0; } } if (contr.key_tap_counter > 0) { contr.key_time_untap++; if (contr.key_time_untap > CONTR_KEY_CNTUNTAP_READY) { contr.key_strokes_ended = true; } if (contr.key_time_untap > CONTR_KEY_CNTUNTAP_CLEAN) { contr.key_was_pressed = false; contr.key_tap_counter = 0; contr.key_time_untap = 0; contr.key_strokes_ended = false; } } else { contr.key_time_untap = 0; } } void contr_key_reset(void) { contr.key_was_pressed = false; contr.key_tap_counter = 0; contr.key_time_untap = 0; contr.key_strokes_ended = false; }