diff --git a/pico_tnc/cmd.c b/pico_tnc/cmd.c index b08a9c6..2530a84 100644 --- a/pico_tnc/cmd.c +++ b/pico_tnc/cmd.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without @@ -99,6 +99,9 @@ static const uint8_t *gps_str[] = { // indicate converse mode bool converse_mode = false; +// indicate calibrate mode +bool calibrate_mode = false; +uint8_t calibrate_idx = 0; static uint8_t *read_call(uint8_t *buf, callsign_t *c) { @@ -547,7 +550,33 @@ static bool cmd_txdelay(tty_t *ttyp, uint8_t *buf, int len) static bool cmd_calibrate(tty_t *ttyp, uint8_t *buf, int len) { - tty_write_str(ttyp, "CALIBRATE\r\n"); + //tty_write_str(ttyp, "CALIBRATE\r\n"); + tnc_t *tp = &tnc[0]; + if (tp->send_state != SP_IDLE) { + tty_write_str(ttyp, "Transmitter busy\r\n"); + return false; + } + + tp->send_state = SP_CALIBRATE; + tp->do_nrzi = false; + calibrate_mode = true; + calibrate_idx = 0; + tp->cal_data = 0x00; + tp->ttyp = ttyp; + tp->cal_time = tnc_time(); + tty_write_str(ttyp, "Calibrate Mode. SP to toggle; ctl C to Exit\r\n"); + return true; +} + +void calibrate(void) +{ + tnc_t *tp = &tnc[0]; + if (tp->send_state != SP_CALIBRATE_OFF) return; + + tp->send_state = SP_IDLE; + tp->do_nrzi = true; + calibrate_mode = false; + tty_write_str(tp->ttyp, "Exit Calibrate Mode\r\ncmd: "); } static bool cmd_converse(tty_t *ttyp, uint8_t *buf, int len) @@ -719,7 +748,7 @@ void cmd(tty_t *ttyp, uint8_t *buf, int len) if (matched == 1) { if (mp->func(ttyp, param, param_len)) { - if (!converse_mode) tty_write_str(ttyp, "\r\nOK\r\n"); + if (!(converse_mode | calibrate_mode)) tty_write_str(ttyp, "\r\nOK\r\n"); return; } } diff --git a/pico_tnc/cmd.h b/pico_tnc/cmd.h index f243b5a..c24350e 100644 --- a/pico_tnc/cmd.h +++ b/pico_tnc/cmd.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,5 +32,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. extern bool converse_mode; +extern bool calibrate_mode; +extern uint8_t calibrate_idx; void cmd(tty_t *ttyp, uint8_t *buf, int len); +void calibrate(void); diff --git a/pico_tnc/main.c b/pico_tnc/main.c index 89c250b..d0cc8b4 100644 --- a/pico_tnc/main.c +++ b/pico_tnc/main.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without @@ -148,6 +148,9 @@ int main() // send beacon beacon(); + // calibrate off + calibrate(); + #ifdef BUSY_PIN // gpio_put(BUSY_PIN, 0); #endif diff --git a/pico_tnc/send.c b/pico_tnc/send.c index a914913..e97aa80 100644 --- a/pico_tnc/send.c +++ b/pico_tnc/send.c @@ -63,6 +63,8 @@ static const int ptt_pins[] = { #define ISR_PIN 15 +#define CAL_TIMEOUT (60 * 100) // 60 sec + static void __isr dma_handler(void) { int int_status = dma_hw->ints0; @@ -152,7 +154,11 @@ int send_byte(tnc_t *tp, uint8_t data, bool bit_stuff) int bit = byte & 1; while (byte > 1) { // check sentinel - if (!bit) tp->level ^= 1; // NRZI, invert if original bit == 0 + if (tp->do_nrzi) { + if (!bit) tp->level ^= 1; // NRZI, invert if original bit == 0 + } else { + tp->level = bit; + } // make Bell202 CPAFSK audio samples tp->dma_blocks[tp->next][idx++] = phase_tab[tp->level][tp->phase]; // 1: mark, 0: space @@ -309,17 +315,6 @@ void send_init(void) gpio_put(SMPS_PIN, 1); } -enum SEND_STATE { - SP_IDLE = 0, - SP_WAIT_CLR_CH, - SP_P_PERSISTENCE, - SP_WAIT_SLOTTIME, - SP_PTT_ON, - SP_SEND_FLAGS, - SP_DATA_START, - SP_DATA, - SP_ERROR, -}; int send_queue_free(tnc_t *tp) { @@ -434,6 +429,15 @@ void send(void) while (queue_try_remove(&tp->send_queue, &data)) { } tp->send_state = SP_IDLE; + break; + + case SP_CALIBRATE: + if (tnc_time() - tp->cal_time >= CAL_TIMEOUT) { + tp->send_state = SP_CALIBRATE_OFF; + } else { + send_byte(tp, tp->cal_data, false); + } + break; } tp++; diff --git a/pico_tnc/serial.c b/pico_tnc/serial.c index 2b99170..bfb0587 100644 --- a/pico_tnc/serial.c +++ b/pico_tnc/serial.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/pico_tnc/tnc.c b/pico_tnc/tnc.c index 0a5cc7a..db5d461 100644 --- a/pico_tnc/tnc.c +++ b/pico_tnc/tnc.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without @@ -95,12 +95,16 @@ void tnc_init(void) // send queue queue_init(&tp->send_queue, sizeof(uint8_t), SEND_QUEUE_LEN); + tp->send_state = SP_IDLE; tp->cdt = 0; tp->kiss_txdelay = 50; tp->kiss_p = 63; tp->kiss_slottime = 10; tp->kiss_fullduplex = 0; + + // calibrate + tp->do_nrzi = true; } //printf("%d ports support\n", PORT_N); diff --git a/pico_tnc/tnc.h b/pico_tnc/tnc.h index 916198d..07dc40b 100644 --- a/pico_tnc/tnc.h +++ b/pico_tnc/tnc.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without @@ -85,6 +85,8 @@ typedef struct { int high_q; } values_t; +typedef struct TTY tty_t; + typedef struct TNC { uint8_t port; @@ -177,6 +179,12 @@ typedef struct TNC { uint16_t packet_len; int wait_time; + // calibrate + uint8_t cal_data; + bool do_nrzi; + uint32_t cal_time; + tty_t *ttyp; + } tnc_t; extern tnc_t tnc[]; @@ -256,3 +264,18 @@ typedef struct TTY { } tty_t; extern tty_t tty[]; + +// send process state +enum SEND_STATE { + SP_IDLE = 0, + SP_WAIT_CLR_CH, + SP_P_PERSISTENCE, + SP_WAIT_SLOTTIME, + SP_PTT_ON, + SP_SEND_FLAGS, + SP_DATA_START, + SP_DATA, + SP_ERROR, + SP_CALIBRATE, + SP_CALIBRATE_OFF, +}; diff --git a/pico_tnc/tty.c b/pico_tnc/tty.c index e97e704..1ae9e93 100644 --- a/pico_tnc/tty.c +++ b/pico_tnc/tty.c @@ -1,5 +1,5 @@ /* -Copyright (c) 2021, Kazuhisa Yokota, JN1DFF +Copyright (c) 2021, JN1DFF All rights reserved. Redistribution and use in source and binary forms, with or without @@ -112,8 +112,21 @@ void tty_write_str(tty_t *ttyp, uint8_t const *str) #define BELL '\a' #define CTRL_C '\x03' #define FEND 0xc0 +#define SP ' ' #define KISS_TIMEOUT (1 * 100) // 1 sec + +#define CAL_DATA_MAX 3 + +static const uint8_t calibrate_data[CAL_DATA_MAX] = { + 0x00, 0xff, 0x55, +}; + +static const char *calibrate_str[CAL_DATA_MAX] = { + "send space (2200Hz)\r\n", + "send mark (1200Hz)\r\n", + "send 0x55 (1200/2200Hz)\r\n", +}; void tty_input(tty_t *ttyp, int ch) { @@ -128,6 +141,28 @@ void tty_input(tty_t *ttyp, int ch) ttyp->kiss_state = KISS_OUTSIDE; } + // calibrate mode + if (calibrate_mode) { + tnc_t *tp = &tnc[0]; + + switch (ch) { + case SP: // toggle mark/space + if (++calibrate_idx >= CAL_DATA_MAX) calibrate_idx = 0; + tp->cal_data = calibrate_data[calibrate_idx]; + tty_write_str(ttyp, calibrate_str[calibrate_idx]); + tp->cal_time = tnc_time(); + break; + + case CTRL_C: + tp->send_state = SP_CALIBRATE_OFF; + break; + + default: + tty_write_char(ttyp, BELL); + } + return; + } + switch (ch) { case FEND: // KISS frame end kiss_input(ttyp, ch); @@ -153,7 +188,7 @@ void tty_input(tty_t *ttyp, int ch) cmd(ttyp, ttyp->cmd_buf, ttyp->cmd_idx); } } - if (!converse_mode) tty_write_str(ttyp, "cmd: "); + if (!(converse_mode | calibrate_mode)) tty_write_str(ttyp, "cmd: "); ttyp->cmd_idx = 0; break;