initial release

master
amedes 2021-10-09 21:10:08 +09:00
commit f2fed45315
53 zmienionych plików z 9372 dodań i 0 usunięć

4
.gitignore vendored 100644
Wyświetl plik

@ -0,0 +1,4 @@
#
build/
*.un
*~

15
CMakeLists.txt 100644
Wyświetl plik

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.12)
include(pico_sdk_import.cmake)
project(pico_examples C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(PICO_EXAMPLES_PATH ${PROJECT_SOURCE_DIR})
pico_sdk_init()
include(example_auto_set_url.cmake)
add_subdirectory(pico_tnc)

24
LICENSE 100644
Wyświetl plik

@ -0,0 +1,24 @@
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

29
README.md 100644
Wyświetl plik

@ -0,0 +1,29 @@
# PICO TNC
PICO TNC is the Terminal Node Controler for Amateur Packet Radio powered by Raspberry Pi Pico.
This TNC has same functionality as WB8WGA's PIC TNC.
## PIC TNC features
- Digipeat UI packet up to 1024 byte length
- Send beacon packet
- Support converse mode
- Support GPS tracker feature
- Support both USB serial and UART serial interface
## Additional features
- Support KISS mode
- Support multi-port up to 3 ports
## How to build
`cd pico_tnc`
`mkdir build`
`cd build`
`cmake ..`
`make -j4`
![command line](command.png)
[![schemantic](schematic.jpg)](schematic.png)

BIN
command.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 24 KiB

Wyświetl plik

@ -0,0 +1,5 @@
set(PICO_EXAMPLE_URL_BASE "https://github.com/raspberrypi/pico-examples/tree/HEAD")
macro(example_auto_set_url TARGET)
file(RELATIVE_PATH URL_REL_PATH "${PICO_EXAMPLES_PATH}" "${CMAKE_CURRENT_LIST_DIR}")
pico_set_program_url(${TARGET} "${PICO_EXAMPLE_URL_BASE}/${URL_REL_PATH}")
endmacro()

Wyświetl plik

@ -0,0 +1,62 @@
# This is a copy of <PICO_EXTRAS_PATH>/external/pico_extras_import.cmake
# This can be dropped into an external project to help locate pico-extras
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_EXTRAS_PATH} AND (NOT PICO_EXTRAS_PATH))
set(PICO_EXTRAS_PATH $ENV{PICO_EXTRAS_PATH})
message("Using PICO_EXTRAS_PATH from environment ('${PICO_EXTRAS_PATH}')")
endif ()
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT))
set(PICO_EXTRAS_FETCH_FROM_GIT $ENV{PICO_EXTRAS_FETCH_FROM_GIT})
message("Using PICO_EXTRAS_FETCH_FROM_GIT from environment ('${PICO_EXTRAS_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH} AND (NOT PICO_EXTRAS_FETCH_FROM_GIT_PATH))
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH $ENV{PICO_EXTRAS_FETCH_FROM_GIT_PATH})
message("Using PICO_EXTRAS_FETCH_FROM_GIT_PATH from environment ('${PICO_EXTRAS_FETCH_FROM_GIT_PATH}')")
endif ()
if (NOT PICO_EXTRAS_PATH)
if (PICO_EXTRAS_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_EXTRAS_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
PICO_EXTRAS
GIT_REPOSITORY https://github.com/raspberrypi/pico-extras
GIT_TAG master
)
if (NOT PICO_EXTRAS)
message("Downloading PICO EXTRAS")
FetchContent_Populate(PICO_EXTRAS)
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
if (PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pico-extras")
set(PICO_EXTRAS_PATH ${PICO_SDK_PATH}/../pico-extras)
message("Defaulting PICO_EXTRAS_PATH as sibling of PICO_SDK_PATH: ${PICO_EXTRAS_PATH}")
else()
message(FATAL_ERROR
"PICO EXTRAS location was not specified. Please set PICO_EXTRAS_PATH or set PICO_EXTRAS_FETCH_FROM_GIT to on to fetch from git."
)
endif()
endif ()
endif ()
set(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" CACHE PATH "Path to the PICO EXTRAS")
set(PICO_EXTRAS_FETCH_FROM_GIT "${PICO_EXTRAS_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO EXTRAS from git if not otherwise locatable")
set(PICO_EXTRAS_FETCH_FROM_GIT_PATH "${PICO_EXTRAS_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download EXTRAS")
get_filename_component(PICO_EXTRAS_PATH "${PICO_EXTRAS_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_EXTRAS_PATH})
message(FATAL_ERROR "Directory '${PICO_EXTRAS_PATH}' not found")
endif ()
set(PICO_EXTRAS_PATH ${PICO_EXTRAS_PATH} CACHE PATH "Path to the PICO EXTRAS" FORCE)
add_subdirectory(${PICO_EXTRAS_PATH} pico_extras)

Wyświetl plik

@ -0,0 +1,62 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})

Wyświetl plik

@ -0,0 +1,49 @@
add_executable(pico_tnc
main.c
tnc.c
send.c
receive.c
decode.c
filter.c
bell202.c
ax25.c
test.c
packet_table.c
usb_input.c
usb_output.c
cmd.c
serial.c
tty.c
flash.c
gps.c
unproto.c
digipeat.c
beacon.c
kiss.c
)
target_include_directories(pico_tnc PRIVATE
include
)
target_link_libraries(pico_tnc
pico_stdlib
#pico_stdio_uart
#pico_stdio_usb
hardware_adc
hardware_dma
hardware_pwm
hardware_uart
# For the dummy output:
#hardware_pio
#pico_multicore
)
pico_enable_stdio_usb(pico_tnc 1)
pico_enable_stdio_uart(pico_tnc 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(pico_tnc)
# add url via pico_set_program_url
example_auto_set_url(pico_tnc)

143
pico_tnc/ax25.c 100644
Wyświetl plik

@ -0,0 +1,143 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
calculate CCITT-16 CRC using DMA CRC hardware
*/
#include <stdio.h>
#include "pico/stdlib.h"
#ifdef RASPBERRYPI_PICO
#include "hardware/dma.h"
#include "ax25.h"
#define OUT_INV (1 << 11)
#define OUT_REV (1 << 10)
int ax25_fcs(uint32_t crc, const uint8_t *data, int size)
{
uint8_t dummy;
int dma_chan = dma_claim_unused_channel(true);
dma_channel_config c = dma_channel_get_default_config(dma_chan);
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
channel_config_set_write_increment(&c, false);
channel_config_set_read_increment(&c, true);
channel_config_set_dreq(&c, DREQ_FORCE);
dma_channel_configure(
dma_chan,
&c,
&dummy,
data,
size,
false
);
// enable sniffer
dma_sniffer_enable(dma_chan, 0x3, true);
dma_hw->sniff_ctrl |= OUT_INV | OUT_REV;
dma_hw->sniff_data = crc;
dma_hw->sniff_data >>= 16;
// start DMA
dma_channel_start(dma_chan);
// wait for finish
dma_channel_wait_for_finish_blocking(dma_chan);
dma_channel_unclaim(dma_chan);
return dma_hw->sniff_data >> 16;
}
#else
#define CRC16_POLY 0x10811 /* G(x) = 1 + x^5 + x^12 + x^16 */
int ax25_fcs(int crc, const uint8_t packet[], int length)
{
uint32_t crc;
int i, j;
if (length <= 0) return -1; // packet too short
// calculate CRC x^16 + x^12 + x^5 + 1
crc = 0xffff; /* initial value */
for (i = 0; i < length; i++) {
crc ^= packet[i];
for (j = 0; j < 8; j++) {
if (crc & 1) crc ^= CRC16_POLY;
crc >>= 1;
}
}
crc ^= 0xffff; // invert
return crc;
}
#endif
bool ax25_callcmp(callsign_t *c, uint8_t *addr)
{
for (int i = 0; i < 6; i++) {
if (c->call[i] != (addr[i] >> 1)) return false;
}
if (c->ssid == ((addr[6] >> 1) & 0x0f)) return true;
return false;
}
void ax25_mkax25addr(uint8_t *addr, callsign_t *c)
{
uint8_t *s = addr;
for (int i = 0; i < 6; i++) {
*s++ = c->call[i] << 1;
}
// SSID
*s = (c->ssid << 1) | 0x60;
}
bool ax25_ui(uint8_t *packet, int len)
{
int i;
i = AX25_ADDR_LEN - 1; // SSID
while (i < len) {
if (packet[i] & 1) break; // address extension bit
i += AX25_ADDR_LEN;
}
i++;
if (i + 2 > len) return false; // no control and PID field
return packet[i] == 0x03 && packet[i+1] == 0xf0; // true if UI packet
}

41
pico_tnc/ax25.h 100644
Wyświetl plik

@ -0,0 +1,41 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <stdio.h>
#define AX25_ADDR_LEN 7
typedef struct CALLSIGN {
char call[6];
uint8_t ssid;
} callsign_t;
int ax25_fcs(uint32_t crc, const uint8_t const *data, int size);
bool ax25_callcmp(callsign_t *c, uint8_t *addr);
void ax25_mkax25addr(uint8_t *addr, callsign_t *c);
bool ax25_ui(uint8_t *packet, int len);

50
pico_tnc/beacon.c 100644
Wyświetl plik

@ -0,0 +1,50 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "tnc.h"
#include "unproto.h"
static uint32_t beacon_time = 0;
void beacon_reset(void)
{
beacon_time = tnc_time();
}
void beacon(void)
{
if (!param.beacon) return;
if (tnc_time() - beacon_time < param.beacon * 60 * 100) return; // convert minutes to 10 ms
send_unproto(&tnc[BEACON_PORT], param.btext, strlen(param.btext));
beacon_time = tnc_time();
}

31
pico_tnc/beacon.h 100644
Wyświetl plik

@ -0,0 +1,31 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
void beacon(void);
void beacon_reset(void);

214
pico_tnc/bell202.c 100644
Wyświetl plik

@ -0,0 +1,214 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdint.h>
#include <math.h>
//#include "timer.h"
#include "filter.h"
#include "tnc.h"
int bell202_decode(tnc_t *tp, int adc)
{
int m;
int sum;
int val;
//fprintf(stderr,"adc = %d\n");
//val = input_bpf(adc);
// Bandpass filter
val = filter(&tp->bpf, adc) >> ADC_BIT;
//val = adc;
//printf("val = %d\n", val);
m = val * tp->delayed[tp->delay_idx];
//printf("val = %d, m = %d\n", val, m);
//printf("%d\n", m);
tp->delayed[tp->delay_idx] = val;
if (++tp->delay_idx >= DELAYED_N) tp->delay_idx = 0;
#if 0
x[x_idx] = m >> 12;
sum = 0;
for (i = 0; i < FIR_LPF_N; i++) {
sum += an[i] * x[(x_idx + i) % FIR_LPF_N];
#if 0
if (sum > (1 << 30)) printf("%d,", sum);
else
if (sum < -(1 << 30)) printf("%d,", sum);
#endif
}
x_idx += FIR_LPF_N - 1;
x_idx %= FIR_LPF_N;
//printf("%d, %d, %d\n", adc, m >> 8, sum >> 8);
#else
sum = filter(&tp->lpf, m >> 16);
//printf("%d, %d, %d, %d\n", adc, val, m, sum);
#endif
#ifdef LPF_FLOAT
return sum * 65536;
#else
return sum;
#endif
}
#ifdef BELL202_SYNC
#define LOW_N SAMPLING_N
#define HIGH_N (LOW_N * 6 / 11)
static int16_t low_i_tab[LOW_N];
static int16_t low_q_tab[LOW_N];
static int16_t high_i_tab[HIGH_N];
static int16_t high_q_tab[HIGH_N];
static const int16_t low_tab[LOW_N] = {
-15704,
2338,
19637,
30701,
32018,
23170,
6965,
-11451,
-26231,
-32684,
-28759,
};
static const int16_t high_tab[HIGH_N + 1] = {
23170,
-8481,
-31650,
-23170,
8481,
31650,
23170,
};
// Synch decode
int bell202_decode2(tnc_t *tp, int adc)
{
int m;
int sum;
int val;
int i;
values_t *vp;
// Band pass filter
#if ADC_BIT == 8
//val = filter(&tp->bpf, adc) >> 8;
val = filter(&tp->bpf, adc) >> 12;
#else
val = filter(&tp->bpf, adc) >> 12;
#endif
//printf("val = %d\n", val);
vp = &tp->values[tp->values_idx];
// subtract old values
tp->sum_low_i -= vp->low_i;
tp->sum_low_q -= vp->low_q;
tp->sum_high_i -= vp->high_i;
tp->sum_high_q -= vp->high_q;
// add new values
#if 0
tp->sum_low_i += (vp->low_i = val * low_i_tab[tp->low_idx]);
tp->sum_low_q += (vp->low_q = val * low_q_tab[tp->low_idx]);
tp->sum_high_i += (vp->high_i = val * high_i_tab[tp->high_idx]);
tp->sum_high_q += (vp->high_q = val * high_q_tab[tp->high_idx]);
#endif
tp->sum_low_i += (vp->low_i = val * low_tab[tp->low_idx]);
tp->sum_low_q += (vp->low_q = val * low_tab[LOW_N - 1 - tp->low_idx]);
tp->sum_high_i += (vp->high_i = val * high_tab[tp->high_idx]);
tp->sum_high_q += (vp->high_q = val * high_tab[HIGH_N - tp->high_idx]);
int sqr_li = tp->sum_low_i >> 16;
int sqr_lq = tp->sum_low_q >> 16;
int sqr_hi = tp->sum_high_i >> 16;
int sqr_hq = tp->sum_high_q >> 16;
// compare
m = (sqr_li * sqr_li + sqr_lq * sqr_lq)
- (sqr_hi * sqr_hi + sqr_hq * sqr_hq);
// low pass filter
sum = filter(&tp->lpf, m >> 16);
//printf("%d, %d, %d, %d\n", adc, val, m, sum);
// advance indexes
if (++tp->values_idx >= SAMPLING_N) tp->values_idx = 0;
if (++tp->low_idx >= LOW_N) tp->low_idx = 0;
if (++tp->high_idx >= HIGH_N) tp->high_idx = 0;
return sum;
}
#endif // BELL202_SYNC
void bell202_init(void)
{
#ifdef BELL202_SYNC
// initialize sin, cos table
int i;
#define AMP 32767
//printf("bell202: I/Q tables\n");
for (i = 0; i < LOW_N; i++) {
float t = M_PI * 2 * i / LOW_N + M_PI / 4;
low_i_tab[i] = cosf(t) * AMP + 0.5;
low_q_tab[i] = sinf(t) * AMP + 0.5;
printf("%d, %d, ", low_i_tab[i], low_q_tab[i]);
if (i < HIGH_N) {
t = M_PI * 2 * i / HIGH_N + M_PI / 4;
high_i_tab[i] = cosf(t) * AMP + 0.5;
high_q_tab[i] = sinf(t) * AMP + 0.5;
//printf("%d, %d, ", high_i_tab[i], high_q_tab[i]);
}
//printf("\n");
}
#endif
}

34
pico_tnc/bell202.h 100644
Wyświetl plik

@ -0,0 +1,34 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "tnc.h"
int bell202_decode(tnc_t *tp, int adc);
int bell202_decode2(tnc_t *tp, int adc);
void bell202_init(void);

728
pico_tnc/cmd.c 100644
Wyświetl plik

@ -0,0 +1,728 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "pico/stdlib.h"
#include "class/cdc/cdc_device.h"
#include "pico/sync.h"
#include "usb_output.h"
#include "usb_input.h"
#include "ax25.h"
#include "tnc.h"
#include "tty.h"
#include "flash.h"
#include "receive.h"
#include "beacon.h"
typedef struct CMD {
uint8_t *name;
int len;
bool (*func)(tty_t *ttyp, uint8_t *buf, int len);
} cmd_t;
static char const help_str[] =
"\r\n"
"Commands are Case Insensitive\r\n"
"Use Backspace Key (BS) for Correction\r\n"
"Use the DISP command to desplay all options\r\n"
"Insert Jumper J4 and Connect GPS for APRS Operation\r\n"
"Insert Jumper J5 and Connect to Terminal for Command Interpreter\r\n"
"\r\n"
"Commands (with example):\r\n"
"MYCALL (mycall jn1dff-2)\r\n"
"UNPROTO (unproto jn1dff-14 v jn1dff-1) - 3 digis max\r\n"
"BTEXT (btext Bob)-100 chars max\r\n"
"BEACON (beacon every n)- n=0 is off and 1<n<60 mins\r\n"
"MONitor (mon all,mon me, or mon off)\r\n"
"DIGIpeat (digi on or digi off)\r\n"
"MYALIAS (myalias RELAY)\r\n"
"PERM (PERM)\r\n"
"ECHO (echo on or echo off)\r\n"
"GPS (gps $GPGAA or gps $GPGLL or gps $GPRMC)\r\n"
"TRace (tr xmit or tr rcv) - For debugging only\r\n"
"TXDELAY (txdelay n 0<n<201 n is number of delay flags to send)\r\n"
"CALIBRATE (Calibrate Mode - Testing Only)\r\n"
"\r\n";
enum STATE_CALLSIGN {
CALL = 0,
HYPHEN,
SSID1,
SSID2,
SPACE,
END,
};
enum TRACE {
TR_OFF = 0,
TR_XMIT,
TR_RCV,
};
static const uint8_t *gps_str[] = {
"$GPGGA",
"$GPGLL",
"$GPRMC",
};
// indicate converse mode
bool converse_mode = false;
static uint8_t *read_call(uint8_t *buf, callsign_t *c)
{
callsign_t cs;
int i, j;
int state = CALL;
bool error = false;
cs.call[i] = '\0';
for (i = 1; i < 6; i++) cs.call[i] = ' ';
cs.ssid = 0;
// callsign
j = 0;
for (i = 0; buf[i] && state != END; i++) {
int ch = buf[i];
switch (state) {
case CALL:
if (isalnum(ch)) {
cs.call[j++] = toupper(ch);
if (j >= 6) state = HYPHEN;
break;
} else if (ch == '-') {
state = SSID1;
break;
} else if (ch != ' ') {
error = true;
}
state = END;
break;
case HYPHEN:
if (ch == '-') {
state = SSID1;
break;
}
if (ch != ' ') {
error = true;
}
state = END;
break;
case SSID1:
if (isdigit(ch)) {
cs.ssid = ch - '0';
state = SSID2;
break;
}
error = true;
state = END;
break;
case SSID2:
if (isdigit(ch)) {
cs.ssid *= 10;
cs.ssid += ch - '0';
state = SPACE;
break;
}
/* FALLTHROUGH */
case SPACE:
if (ch != ' ') error = true;
state = END;
}
}
if (cs.ssid > 15) error = true;
if (error) return NULL;
memcpy(c, &cs, sizeof(cs));
return &buf[i];
}
static int callsign2ascii(uint8_t *buf, callsign_t *c)
{
int i;
if (!c->call[0]) {
memcpy(buf, "NOCALL", 7);
return 6;
}
for (i = 0; i < 6; i++) {
int ch = c->call[i];
if (ch == ' ') break;
buf[i] = ch;
}
if (c->ssid > 0) {
buf[i++] = '-';
if (c->ssid > 9) {
buf[i++] = '1';
buf[i++] = c->ssid - 10 + '0';
} else {
buf[i++] = c->ssid + '0';
}
}
buf[i] = '\0';
return i;
}
static bool cmd_mycall(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
return read_call(buf, &param.mycall) != NULL;
//usb_write(buf, len);
//usb_write("\r\n", 2);
} else {
uint8_t temp[10];
tty_write_str(ttyp, "MYCALL ");
tty_write(ttyp, temp, callsign2ascii(temp, &param.mycall));
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_unproto(tty_t *ttyp, uint8_t *buf, int len)
{
int i;
uint8_t *p;
if (buf && buf[0]) {
p = read_call(buf, &param.unproto[0]);
if (p == NULL) return false;
for (i = 1; i < UNPROTO_N; i++) param.unproto[i].call[0] = '\0';
for (i = 1; *p && i < 4; i++) {
while (*p == ' ') p++;
if (toupper(*p) != 'V') return false;
p++;
if (*p != ' ') return false;
while (*p == ' ') p++;
p = read_call(p, &param.unproto[i]);
if (p == NULL) return false;
}
} else {
tty_write_str(ttyp, "UNPROTO ");
for (i = 0; i < 4; i++) {
uint8_t temp[10];
if (!param.unproto[i].call[0]) break;
if (i > 0) tty_write_str(ttyp, " V ");
tty_write(ttyp, temp, callsign2ascii(temp, &param.unproto[i]));
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_btext(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
uint8_t *p = buf;
int i;
if (buf[0] == '%' && len == 1) {
param.btext[0] = '\0';
return true;
}
for (i = 0; i < len && i < BTEXT_LEN; i++) {
param.btext[i] = buf[i];
}
param.btext[i] = '\0';
} else {
tty_write_str(ttyp, "BTEXT ");
tty_write_str(ttyp, param.btext);
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_beacon(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
static uint8_t const every[] = "EVERY";
uint8_t const *s = every;
int i = 0;
if (!strncasecmp(buf, "OFF", 3)) {
param.beacon = 0;
return true;
}
while (toupper(buf[i]) == *s) {
i++;
s++;
}
if (!buf[i] || buf[i] != ' ') return false;
int r, t;
r = sscanf(&buf[i], "%d", &t);
if (r != 1 || (t < 0 || t > 60)) return false;
param.beacon = t;
beacon_reset(); // beacon timer reset
} else {
tty_write_str(ttyp, "BEACON ");
if (param.beacon > 0) {
uint8_t temp[4];
tty_write_str(ttyp, "On EVERY ");
tty_write(ttyp, temp, sprintf(temp, "%u", param.beacon));
} else {
tty_write_str(ttyp, "Off");
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_monitor(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
if (!strncasecmp(buf, "ALL", 3)) {
param.mon = MON_ALL;
} else if (!strncasecmp(buf, "ME", 2)) {
param.mon = MON_ME;
} else if (!strncasecmp(buf, "OFF", 3)) {
param.mon = MON_OFF;
} else {
return false;
}
} else {
tty_write_str(ttyp, "MONitor ");
if (param.mon == MON_ALL) {
tty_write_str(ttyp, "ALL");
} else if (param.mon == MON_ME) {
tty_write_str(ttyp, "ME");
} else {
tty_write_str(ttyp, "OFF");
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_digipeat(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
if (!strncasecmp(buf, "ON", 2)) {
param.digi = true;
} else if (!strncasecmp(buf, "OFF", 3)) {
param.digi = false;
} else {
return false;
}
} else {
tty_write_str(ttyp, "DIGIpeater ");
if (param.digi) {
tty_write_str(ttyp, "ON");
} else {
tty_write_str(ttyp, "OFF");
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_myalias(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
return read_call(buf, &param.myalias) != NULL;
//usb_write(buf, len);
//usb_write("\r\n", 2);
} else {
uint8_t call[10];
tty_write_str(ttyp, "MYALIAS ");
if (param.myalias.call[0]) tty_write(ttyp, call, callsign2ascii(call, &param.myalias));
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_perm(tty_t *ttyp, uint8_t *buf, int len)
{
//tty_write("PERM\r\n", 6);
receive_off(); // stop ADC free running
bool ret = flash_write(&param, sizeof(param));
receive_on();
return ret;
}
static bool cmd_echo(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
if (!strncasecmp(buf, "ON", 2)) {
param.echo = 1;
} else if (!strncasecmp(buf, "OFF", 3)) {
param.echo = 0;
} else {
return false;
}
} else {
tty_write_str(ttyp, "ECHO ");
if (param.echo) {
tty_write_str(ttyp, "ON");
} else {
tty_write_str(ttyp, "OFF");
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_gps(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
for (int i = 0; i < 3; i++) {
uint8_t const *str = gps_str[i];
if (!strncasecmp(buf, str, strlen(str))) {
param.gps = i;
return true;
}
}
return false;
} else {
tty_write_str(ttyp, "GPS ");
tty_write_str(ttyp, gps_str[param.gps]);
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_trace(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
if (!strncasecmp(buf, "OFF", 3)) {
param.trace = TR_OFF;
} else if (!strncasecmp(buf, "XMIT", 4)) {
param.trace = TR_XMIT;
} else if (!strncasecmp(buf, "RCV", 3)) {
param.trace = TR_RCV;
} else {
return false;
}
} else {
tty_write_str(ttyp, "TRace ");
if (param.trace == TR_XMIT) {
tty_write_str(ttyp, "XMIT");
} else if (param.trace == TR_RCV) {
tty_write_str(ttyp, "RCV");
} else {
tty_write_str(ttyp, "OFF");
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_txdelay(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
int t = atoi(buf);
if (t <= 0 || t > 200) return false;
param.txdelay = t;
// set txdelay
tnc[0].kiss_txdelay = param.txdelay * 2 / 3;
} else {
uint8_t temp[8];
tty_write_str(ttyp, "TXDELAY ");
tty_write(ttyp, temp, snprintf(temp, 8, "%u", param.txdelay));
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_calibrate(tty_t *ttyp, uint8_t *buf, int len)
{
tty_write_str(ttyp, "CALIBRATE\r\n");
}
static bool cmd_converse(tty_t *ttyp, uint8_t *buf, int len)
{
//tty_write("CONVERSE\r\n", 10);
converse_mode = true;
tty_write_str(ttyp, "*** Converse Mode, ctl C to Exit\r\n");
return true;
}
static bool cmd_kiss(tty_t *ttyp, uint8_t *buf, int len)
{
if (buf && buf[0]) {
if (!strncasecmp(buf, "ON", 2)) {
ttyp->kiss_mode = 1;
} else if (!strncasecmp(buf, "OFF", 3)) {
ttyp->kiss_mode = 0;
} else {
return false;
}
} else {
tty_write_str(ttyp, "KISS ");
if (ttyp->kiss_mode) {
tty_write_str(ttyp, "ON");
} else {
tty_write_str(ttyp, "OFF");
}
tty_write_str(ttyp, "\r\n");
}
return true;
}
static bool cmd_help(tty_t *ttyp, uint8_t *buf, int len)
{
//printf("tud_cdc_write_available() = %d\n", tud_cdc_write_available());
tty_write_str(ttyp, help_str);
//printf("tud_cdc_write_available() = %d\n", tud_cdc_write_available());
return true;
}
static bool cmd_disp(tty_t *ttyp, uint8_t *buf, int len)
{
uint8_t temp[10]; // 6 + '-' + 2 + '\0'
tty_write_str(ttyp, "\r\n");
// echo
cmd_echo(ttyp, NULL, 0);
// txdelay
cmd_txdelay(ttyp, NULL, 0);
// gps
cmd_gps(ttyp, NULL, 0);
// trace
cmd_trace(ttyp, NULL, 0);
// monitor
cmd_monitor(ttyp, NULL, 0);
// digipeat
cmd_digipeat(ttyp, NULL, 0);
// beacon
cmd_beacon(ttyp, NULL, 0);
// unproto
cmd_unproto(ttyp, NULL, 0);
// mycall
cmd_mycall(ttyp, NULL, 0);
// myalias
cmd_myalias(ttyp, NULL, 0);
// btext
cmd_btext(ttyp, NULL, 0);
//usb_write("\r\n", 2);
return true;
}
static const cmd_t cmd_list[] = {
{ "HELP", 4, cmd_help, },
{ "?", 1, cmd_help, },
{ "DISP", 4, cmd_disp, },
{ "MYCALL", 6, cmd_mycall, },
{ "UNPROTO", 7, cmd_unproto, },
{ "BTEXT", 6, cmd_btext, },
{ "BEACON", 7, cmd_beacon, },
{ "MONITOR", 8, cmd_monitor, },
{ "DIGIPEAT", 9, cmd_digipeat, },
{ "MYALIAS", 8, cmd_myalias, },
{ "PERM", 4, cmd_perm, },
{ "ECHO", 4, cmd_echo, },
{ "GPS", 3, cmd_gps, },
{ "TRACE", 5, cmd_trace, },
{ "TXDELAY", 7, cmd_txdelay, },
{ "CALIBRATE", 9, cmd_calibrate, },
{ "CONVERSE", 8, cmd_converse, },
{ "K", 1, cmd_converse, },
{ "KISS", 4, cmd_kiss, },
// end mark
{ NULL, 0, NULL, },
};
void cmd(tty_t *ttyp, uint8_t *buf, int len)
{
#if 0
tud_cdc_write(buf, len);
tud_cdc_write("\r\n", 2);
tud_cdc_write_flush();
#endif
uint8_t *top;
int i;
for (i = 0; i < len; i++) {
if (buf[i] != ' ') break;
}
top = &buf[i];
int n = len - i;
if (n <= 0) return;
uint8_t *param = strchr(top, ' ');
int param_len = 0;
if (param) {
n = param - top;
param_len = len - (param - buf);
for (i = 0; i < param_len; i++) {
if (param[i] != ' ') break;
}
param += i;
param_len -= i;
}
cmd_t const *cp = &cmd_list[0], *mp;
int matched = 0;
while (cp->name) {
#if 0
tud_cdc_write(cp->name, cp->len);
tud_cdc_write("\r\n", 2);
tud_cdc_write_flush();
#endif
if (cp->len >= n && !strncasecmp(top, cp->name, n)) {
++matched;
mp = cp;
}
cp++;
}
if (matched == 1) {
if (mp->func(ttyp, param, param_len)) {
if (!converse_mode) tty_write_str(ttyp, "\r\nOK\r\n");
return;
}
}
tty_write_str(ttyp, "\r\n?\r\n");
}

36
pico_tnc/cmd.h 100644
Wyświetl plik

@ -0,0 +1,36 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <stdio.h>
#include "tnc.h"
extern bool converse_mode;
void cmd(tty_t *ttyp, uint8_t *buf, int len);

339
pico_tnc/decode.c 100644
Wyświetl plik

@ -0,0 +1,339 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "pico/stdlib.h"
//#include "timer.h"
#include "tnc.h"
#include "bell202.h"
#include "ax25.h"
#include "usb_output.h"
#include "tty.h"
#include "digipeat.h"
#include "kiss.h"
#define FCS_OK 0x0f47
//#define FCS_OK (0x0f47 ^ 0xffff)
#define MIN_LEN (7 * 2 + 1 + 1 + 2) // Address field *2, Control, PID, FCS
#define STR_LEN 64
static uint8_t str[STR_LEN];
static void display_packet(tty_t *ttyp, tnc_t *tp)
{
int i;
int in_addr = 1;
int len = tp->data_cnt;
uint8_t *data = tp->data;
int size;
#if PORT_N > 1
size = snprintf(str, STR_LEN, "(%d) %d:%d:", tnc_time(), tp->port, tp->pkt_cnt);
tty_write(ttyp, str, size);
#endif
for (i = 0; i < len - 2; i++) {
int c;
if (i < 7) c = data[i + 7]; // src addr
else if (i < 14) c = data[i - 7]; // dst addr
else c = data[i];
if (in_addr) {
int d = c >> 1;
if (i % 7 == 6) { // SSID
if (i >= 7) in_addr = !(data[i] & 1); // check address extension bit
if (d & 0x0f) { // SSID
size = snprintf(str, STR_LEN, "-%d", d & 0x0f);
tty_write(ttyp, str, size);
}
if (i >= 14 && (c & 0x80)) tty_write_char(ttyp, '*'); // H bit
if (i == 6) tty_write_char(ttyp, '>');
else tty_write_char(ttyp, in_addr ? ',' : ':');
} else { // CALLSIGN
if (d >= '0' && d <= '9') tty_write_char(ttyp, d);
else if (d >= 'A' && d <= 'Z') tty_write_char(ttyp, d);
else if (d != ' ') {
size = snprintf(str, STR_LEN, "<%02x>", d);
tty_write(ttyp, str, size);
}
}
} else {
if (c >= ' ' && c <= '~') tty_write_char(ttyp, c);
else {
size = snprintf(str, STR_LEN, "<%02x>", c);
tty_write(ttyp, str, size);
}
}
}
#if 1
tty_write_str(ttyp, "\r\n");
#else
size = snprintf(str, STR_LEN, "<%02x%02x>\r\n", data[len-1], data[len-2]);
tty_write(ttyp, str, size);
#endif
}
static void output_packet(tnc_t *tp)
{
int len = tp->data_cnt;
uint8_t *data = tp->data;
if (len < MIN_LEN) return;
// FCS check
if (ax25_fcs(0, data, len) != FCS_OK) return;
// count received packet
++tp->pkt_cnt;
// digipeat
if (param.digi) digipeat(tp);
for (int i = TTY_USB; i <= TTY_UART0; i++) {
tty_t *ttyp = &tty[i];
if (ttyp->kiss_mode) kiss_output(ttyp, tp); // kiss mode
else {
// TNC MONitor command
switch (param.mon) {
case MON_ALL:
display_packet(ttyp, tp);
break;
case MON_ME:
if (ax25_callcmp(&param.mycall, &data[0])) { // dst addr check
display_packet(ttyp, tp);
}
}
}
}
}
#define AX25_FLAG 0x7e
static void decode_bit(tnc_t *tp, int bit)
{
tp->flag <<= 1;
tp->flag |= bit;
switch (tp->state) {
case FLAG:
if (tp->flag == AX25_FLAG) { // found flag
tp->state = DATA;
tp->data_cnt = 0;
tp->data_bit_cnt = 0;
//fprintf(stderr, "found AX25_FALG\n");
}
break;
case DATA:
if ((tp->flag & 0x3f) == 0x3f) { // AX.25 flag, end of packet, six continuous "1" bits
output_packet(tp);
tp->state = FLAG;
break;
}
if ((tp->flag & 0x3f) == 0x3e) break; // delete bit stuffing bit
tp->data_byte >>= 1;
tp->data_byte |= bit << 7;
tp->data_bit_cnt++;
if (tp->data_bit_cnt >= 8) {
if (tp->data_cnt < DATA_LEN) tp->data[tp->data_cnt++] = tp->data_byte;
else {
printf("packet too long > %d\n", tp->data_cnt);
tp->state = FLAG;
break;
}
tp->data_bit_cnt = 0;
}
}
}
static void decode(tnc_t *tp, int val)
{
tp->edge++;
if (val != tp->pval) {
// int bits = (edge + SAMPLING_N/2) / SAMPLING_N;
int bits = (tp->edge * BAUD_RATE*2 + SAMPLING_RATE) / (SAMPLING_RATE * 2);
//printf("%d,", bits);
decode_bit(tp, 0); // NRZI
while (--bits > 0) {
decode_bit(tp, 1);
}
tp->edge = 0;
tp->pval = val;
}
}
#define PLL_STEP ((int)(((1ULL << 32) + SAMPLING_N/2) / SAMPLING_N))
// DireWolf PLL
static void decode2(tnc_t *tp, int val)
{
int32_t prev_pll = tp->pll_counter >> 31; // compiler bug workaround
tp->pll_counter += PLL_STEP;
if ((tp->pll_counter >> 31) < prev_pll) { // overflow
decode_bit(tp, val == tp->nrzi); // decode NRZI
tp->nrzi = val;
}
if (val != tp->pval) {
// adjust PLL counter
tp->pll_counter -= tp->pll_counter >> 2; // 0.75
tp->pval = val;
}
}
void demodulator(tnc_t *tp, int adc)
{
int val;
int bit;
//printf("%d,", adc);
//dac_output_voltage(DAC_CHANNEL_1, adc >> 4);
#define AVERAGE_MUL 256
#define AVERAGE_N 64
#define AVERAGE_SHIFT 6
#define CDT_AVG_N 128
#define CDT_MUL 256
#define CDT_SHIFT 6
// update average value
tp->avg += (adc * AVERAGE_MUL - tp->avg) >> AVERAGE_SHIFT;
val = adc - (tp->avg + AVERAGE_MUL/2) / AVERAGE_MUL;
// carrier detect
tp->cdt_lvl += (val * val * CDT_MUL - tp->cdt_lvl) >> CDT_SHIFT;
#if 0
static int count = 0;
if ((++count & ((1 << 16) - 1)) == 0) {
printf("(%u) decode: adc: %d, cdt_lvl: %d, avg: %d, port = %d\n", tnc_time(), adc, tp->cdt_lvl, tp->avg, tp->port);
}
#endif
#define CDT_THR_LOW 1024
#define CDT_THR_HIGH (CDT_THR_LOW * 2) // low +6dB
if (!tp->cdt && tp->cdt_lvl > CDT_THR_HIGH) { // CDT on
gpio_put(tp->cdt_pin, 1);
tp->cdt = true;
//printf("(%u) decode: CDT on, adc: %d, cdt_lvl: %d, avg: %d, port = %d\n", tnc_time(), adc, tp->cdt_lvl, tp->avg, tp->port);
//printf("(%u) decode: cdt on, port = %d\n", tnc_time(), tp->port);
} else if (tp->cdt && tp->cdt_lvl < CDT_THR_LOW) { // CDT off
gpio_put(tp->cdt_pin, 0);
tp->cdt = false;
//printf("(%u) decode: CDT off, adc: %d, cdt_lvl: %d, avg: %d, port = %d\n", tnc_time(), adc, tp->cdt_lvl, tp->avg, tp->port);
//printf("(%u) decode: cdt off, port = %d\n", tnc_time(), tp->port);
}
if (!tp->cdt) return;
#if 0
sum += adc;
if (++count >= AVERAGE_N) {
average = sum / AVERAGE_N;
//ESP_LOGI(TAG, "average adc value = %d", average);
sum = 0;
count = 0;
}
#else
//tp->average = (tp->average * (AVERAGE_N - 1) + adc + AVERAGE_N/2) / AVERAGE_N;
/*
if (count >= 13200) {
printf("average = %d\n", average);
count = 0;
}
*/
#endif
#define LPF_N SAMPLING_N
//val = bell202_decode((int)adc - average);
//val = bell202_decode((int)adc - 2048);
//val = bell202_decode(tp, adc); // delayed decode
#ifdef BELL202_SYNC
val = bell202_decode2(tp, adc); // sync decode
#else
val = bell202_decode(tp, adc); // delayed decode
#endif
//lpf = (lpf * (LPF_N-1) + val) / LPF_N;
//printf("demodulator(%d) = %d\n", adc, val);
#if 0
static uint32_t count = 0;
if (count < 132) {
printf("%d, %d\n", adc, val);
}
if (++count >= 13200 * 10) {
count = 0;
printf("----------------\n");
}
#endif
#define LPF_THRESHOLD (1 << 12)
//printf("bit val = %d\n", val);
if (val < -LPF_THRESHOLD) tp->bit = 1;
else if (val >= LPF_THRESHOLD) tp->bit = 0;
//dac_output_voltage(DAC_CHANNEL_2, bit * 128);
//printf("%d\n", bit);
#ifdef DECODE_PLL
decode2(tp, tp->bit); // Direwolf PLL
#else
decode(tp, tp->bit); // bit length
#endif
}

30
pico_tnc/decode.h 100644
Wyświetl plik

@ -0,0 +1,30 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "tnc.h"
void demodulator(tnc_t *tp, int adc);

Wyświetl plik

@ -0,0 +1,79 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "tnc.h"
#include "ax25.h"
#include "send.h"
#define SSID_LOC 6
#define H_BIT 0x80
#define AX25_MIN_LEN (7 + 7 + 1 + 1) // dst, src, control, PID
#define MAX_DIGIPEATER 8
static const uint8_t con_pid_ui[2] = { 0x03, 0xf0, };
void digipeat(tnc_t *tp)
{
uint8_t *packet = tp->data;
int len = tp->data_cnt;
if (len < AX25_MIN_LEN) return; // too short
if (!ax25_ui(packet, len)) return; // not UI packet
int offset = AX25_ADDR_LEN; // src addr
if (packet[offset + SSID_LOC] & 1) return; // no repeaters
offset += AX25_ADDR_LEN; // 1st digipeater addr
int digis = 1;
while (offset + AX25_ADDR_LEN <= len) {
if (!(packet[offset + SSID_LOC] & H_BIT)) { // has not been digipeated yet
if (ax25_callcmp(&param.mycall, &packet[offset])
|| ax25_callcmp(&param.myalias, &packet[offset])) { // addr matched
packet[offset + SSID_LOC] |= H_BIT; // set H bit
send_packet(tp, packet, len - 2); // delete FCS
packet[offset + SSID_LOC] &= ~H_BIT; // clear H bit
}
break;
}
if (++digis >= MAX_DIGIPEATER) return;
offset += AX25_ADDR_LEN; // next digipeater addr
}
}

Wyświetl plik

@ -0,0 +1,31 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "tnc.h"
void digipeat(tnc_t *tp);

172
pico_tnc/filter.c 100644
Wyświetl plik

@ -0,0 +1,172 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* fir_filter.c
*
* FIR filter routine
*/
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>
//#include <xtensa/config/core.h>
//#include <esp_log.h>
#include "filter.h"
#include "tnc.h"
#define TAG "filter"
//#define OVERFLOW_CHECK 1
int filter(filter_t *fp, int value)
{
int32_t sum = 0;
int i;
int an_idx;
#ifdef OVERFLOW_CHECK
int64_t suml = 0;
#endif
//if (x_idx == 0) printf("%d ", adc);
//
fp->x[fp->index] = value;
// index of circular buffer
an_idx = fp->size - 1 - fp->index;
if (++fp->index >= fp->size) fp->index = 0;
for (i = 0; i < fp->size; i++) {
int v = fp->an[an_idx + i] * fp->x[i];
sum += v;
#ifdef OVERFLOW_CHECK
suml += v;
#endif
}
#if 0
static int max = 0;
static int min = (1LL << 31) - 1;
if (sum > max) {
max = sum;
printf("max = %d\n", max);
} else if (sum < min) {
min = sum;
printf("min = %d\n", min);
}
#endif
#ifdef OVERFLOW_CHECK
if (sum != suml) {
printf("overflow: sum = %d, suml = %lld\n", sum, suml);
abort();
}
#endif
//if (--fp->an_idx < 0) fp->an_idx = fp->size - 1;
//printf("value = %d, sum = %d, sum >> 16 = %d\n", value, sum, sum >> 16);
return sum;
}
// sinc function
static float sinc(float x)
{
if (fabsf(x) < 1e-6) return 1.0;
return sinf(x) / x;
}
// window function
static float windowf(float x)
{
return 0.54 + 0.46 * cosf(x);
}
// low pass filter initialization
int16_t *filter_coeff(filter_param_t const *f)
{
// calculate FIR coefficient
const int fp = f->pass_freq; // pass frequency
const int fc = f->cutoff_freq; // cut off frequency
const int fck = f->sampling_freq; // sampling frequency
const int size = f->size;
//const float Tck = 1.0 / fck;
const float Rp = (float)fp / (float)fck;
const float Rc = (float)fc / (float)fck;
//const int M = 7;
const int M = (size - 1) / 2;
const int A = 1 << 15; // amplitude
int16_t *an;
int n;
//fprintf(stderr, "size = %d, sampling freq = %d, pass freq = %d, cutoff freq = %d\n",
// f->size, f->sampling_freq, f->pass_freq, f->cutoff_freq);
an = calloc(size * 2 - 1, sizeof(int16_t));
if (an == NULL) {
perror("calloc fail");
exit(1);
}
// finite impulse response
for (n = -M; n <= M; n++) {
int val;
val = A * 2 * (Rc * sinc(2 * M_PI * Rc * n) - Rp * sinc(2 * M_PI * Rp * n)) * windowf(M_PI * n / M) + 0.5;
an[n + M] = val;
//an[n + M] = 2 * R * A * sinc(2 * M_PI * R * n);
//fprintf(stderr, "an[%d] = %d\n", n, an[n + M]);
}
// prepare circular buffer
for (n = 0; n < size - 1; n++) {
an[size + n] = an[n];
}
return an;
}
void filter_init(filter_t *fp, int16_t an[], int size)
{
int16_t *p;
fp->an = an;
fp->size = size;
p = calloc((size + 3) & ~3, sizeof(int16_t));
if (p == NULL) {
perror("calloc");
exit(1);
}
fp->x = p;
}

48
pico_tnc/filter.h 100644
Wyświetl plik

@ -0,0 +1,48 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <stdint.h>
typedef struct FIR_FILTER {
const int16_t *an;
int16_t *x;
int size;
int index;
} filter_t;
typedef struct FILTER_PARAM {
int size;
int sampling_freq;
int pass_freq;
int cutoff_freq;
} filter_param_t;
int filter(filter_t *fp, int value);
void filter_init(filter_t *fp, int16_t an[], int size);
int16_t *filter_coeff(filter_param_t const *f);

109
pico_tnc/flash.c 100644
Wyświetl plik

@ -0,0 +1,109 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/flash.h"
#include "hardware/sync.h"
#define PICO_MAGIC 0x4f434950
extern char __flash_binary_end;
static uint8_t *flash_addr(void)
{
return (uint8_t *)(((uint32_t)&__flash_binary_end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE - 1));
}
static uint8_t *flash_find_id(void)
{
uint8_t *addr = flash_addr();
uint8_t *id = NULL;
for (int page = 0; page < FLASH_SECTOR_SIZE; page += FLASH_PAGE_SIZE) {
if (*(uint32_t *)&addr[page] == PICO_MAGIC) {
id = &addr[page];
} else {
break;
}
}
return id; // return last one
}
static void flash_erase(void)
{
uint32_t flash_offset = (uint32_t)flash_addr() - XIP_BASE;
uint32_t int_save = save_and_disable_interrupts();
busy_wait_us_32(8334); // wait 10 bit period
flash_range_erase(flash_offset, FLASH_SECTOR_SIZE);
restore_interrupts(int_save);
}
static void flash_program(uint8_t *flash, uint8_t *data)
{
if (flash < flash_addr()) return;
if (flash >= (uint8_t *)0x10200000) return; // > 2MB
uint32_t flash_offset = (uint32_t)flash - XIP_BASE;
uint32_t int_save = save_and_disable_interrupts();
busy_wait_us_32(8334); // wait 10 bit period
flash_range_program(flash_offset, data, FLASH_PAGE_SIZE);
restore_interrupts(int_save);
}
bool flash_read(void *data, int len)
{
if (len > FLASH_PAGE_SIZE - sizeof(uint32_t)) return false;
uint8_t *src = flash_find_id();
if (src == NULL) return false;
memcpy(data, src + sizeof(uint32_t), len);
return true;
}
bool flash_write(void *data, int len)
{
if (len > FLASH_PAGE_SIZE - sizeof(uint32_t)) return false;
uint8_t *mem = malloc(FLASH_PAGE_SIZE);
if (mem == NULL) return false;
uint32_t id = PICO_MAGIC;
memcpy(mem, &id, sizeof(id));
memcpy(mem + sizeof(id), data, len);
uint8_t *dst = flash_find_id();
if (!dst) { // flash not initialized
flash_erase();
dst = flash_addr();
} else {
dst += FLASH_PAGE_SIZE;
if (dst - flash_addr() >= FLASH_SECTOR_SIZE) { // no writable area
flash_erase();
dst = flash_addr();
}
}
flash_program(dst, mem);
bool matched = !memcmp(dst, mem, FLASH_PAGE_SIZE);
free(mem);
return matched;
}

5
pico_tnc/flash.h 100644
Wyświetl plik

@ -0,0 +1,5 @@
#pragma once
#include <stdio.h>
bool flash_read(void *data, int len);
bool flash_write(void *data, int len);

83
pico_tnc/gps.c 100644
Wyświetl plik

@ -0,0 +1,83 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "tnc.h"
#include "cmd.h"
#include "usb_output.h"
#include "tnc.h"
#include "usb_input.h"
#include "serial.h"
#include "unproto.h"
#define GPS_LEN 127
#define GPS_INTERVAL (3 * 60 * 100) // 3 min.
#define GPS_PORT 0
// usb echo flag
//uint8_t usb_echo = 1; // on
static uint8_t gps_buf[GPS_LEN + 1];
static int gps_idx = 0;
#define DOLLAR '$'
#define BS '\b'
#define CR '\r'
#define LF '\n'
#define DEL '\x7f'
#define BELL '\a'
static void gps_send(uint8_t *buf, int len)
{
static uint32_t gps_timer = 0;
if (tnc_time() - gps_timer < GPS_INTERVAL) return;
if ((param.gps == GPGGA && !strncmp("$GPGAA", buf, 6))
|| (param.gps == GPGLL && !strncmp("$GPGLL", buf, 6))
|| (param.gps == GPRMC && !strncmp("$GPRMC", buf, 6))) {
send_unproto(&tnc[GPS_PORT], buf, len);
gps_timer = tnc_time();
}
}
void gps_input(int ch)
{
if (ch == DOLLAR) gps_idx = 0;
if (gps_idx < GPS_LEN) gps_buf[gps_idx++] = ch;
if (ch == LF) {
gps_send(gps_buf, gps_idx);
gps_idx = 0;
}
}

29
pico_tnc/gps.h 100644
Wyświetl plik

@ -0,0 +1,29 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
void gps_input(int ch);

196
pico_tnc/kiss.c 100644
Wyświetl plik

@ -0,0 +1,196 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "tnc.h"
#include "send.h"
#include "tty.h"
#define FEND 0xc0
#define FESC 0xdb
#define TFEND 0xdc
#define TFESC 0xdd
#define KISS_PACKET_LEN 1024
enum KISS_COMM {
KISS_DATA = 0,
KISS_TXDELAY,
KISS_P,
KISS_SLOTTIME,
KISS_TXTAIL,
KISS_FULLDUPLEX,
KISS_SETHARDWARE,
};
void kiss_packet(tty_t *ttyp)
{
if (ttyp->kiss_idx == 0) return; // packet length == 0
int type = ttyp->kiss_buf[0]; // kiss type indicator
if (type == 0xff) {
// exit kiss mode
ttyp->kiss_mode = 0;
return;
}
if (ttyp->kiss_idx < 2) return;
int port = type >> 4; // port No.
int comm = type & 0x0f; // command
if (port >= PORT_N) return;
tnc_t *tp = &tnc[port];
int val = ttyp->kiss_buf[1];
// kiss command
switch (comm) {
case KISS_DATA:
// send kiss packet
send_packet(tp, &ttyp->kiss_buf[1], ttyp->kiss_idx - 1); // delete kiss type byte
break;
case KISS_TXDELAY:
tp->kiss_txdelay = val;
break;
case KISS_P:
tp->kiss_p = val;
break;
case KISS_SLOTTIME:
tp->kiss_slottime = val;
break;
case KISS_FULLDUPLEX:
tp->kiss_fullduplex = val;
break;
}
}
void kiss_input(tty_t * ttyp, int ch)
{
switch (ttyp->kiss_state) {
case KISS_OUTSIDE:
if (ch == FEND) {
ttyp->kiss_idx = 0;
ttyp->kiss_timeout = tnc_time();
ttyp->kiss_state = KISS_INSIDE;
}
break;
case KISS_INSIDE:
switch (ch) {
case FEND:
kiss_packet(ttyp); // send kiss packet
ttyp->kiss_state = KISS_OUTSIDE;
break;
case FESC:
ttyp->kiss_state = KISS_FESC;
break;
default:
if (ttyp->kiss_idx >= KISS_PACKET_LEN) {
ttyp->kiss_state = KISS_ERROR;
break;
}
ttyp->kiss_buf[ttyp->kiss_idx++] = ch;
}
break;
case KISS_FESC:
switch (ch) {
case TFEND:
ch = FEND;
break;
case TFESC:
ch = FESC;
break;
}
if (ttyp->kiss_idx >= KISS_PACKET_LEN) {
ttyp->kiss_state = KISS_ERROR;
break;
}
ttyp->kiss_buf[ttyp->kiss_idx++] = ch;
ttyp->kiss_state = KISS_INSIDE;
break;
case KISS_ERROR:
// discard chars until FEND
if (ch == FEND) ttyp->kiss_state = KISS_OUTSIDE;
}
}
void kiss_output(tty_t *ttyp, tnc_t *tp)
{
int len = tp->data_cnt;
uint8_t *data = tp->data;
// KISS start
tty_write_char(ttyp, FEND);
// kiss type, port, data frame 0
uint8_t type = tp->port << 4;
tty_write_char(ttyp, type);
for (int i = 0; i < len - 2; i++) { // delete FCS
int ch = data[i];
switch (ch) {
case FEND:
tty_write_char(ttyp, FESC);
tty_write_char(ttyp, TFEND);
break;
case FESC:
tty_write_char(ttyp, FESC);
tty_write_char(ttyp, TFESC);
break;
default:
tty_write_char(ttyp, ch);
}
}
// KISS end
tty_write_char(ttyp, FEND);
}

43
pico_tnc/kiss.h 100644
Wyświetl plik

@ -0,0 +1,43 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
/*
* kiss.h
*/
#include "tnc.h"
enum KISS_STATE {
KISS_OUTSIDE = 0,
KISS_INSIDE,
KISS_FESC,
KISS_ERROR,
};
void kiss_input(tty_t *ttyp, int ch);
void kiss_output(tty_t *ttyp, tnc_t *tp);

164
pico_tnc/main.c 100644
Wyświetl plik

@ -0,0 +1,164 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "hardware/dma.h"
#include "hardware/pwm.h"
#include "hardware/irq.h"
#include "hardware/sync.h"
#include "hardware/structs/uart.h"
#include "pico/util/queue.h"
#include "hardware/watchdog.h"
#include "tnc.h"
#include "receive.h"
#include "send.h"
#include "ax25.h"
//#define TEST_PACKET 1
#ifdef TEST_PACKET
#include "test.h"
//#include "packet_table.h"
#endif
#include "cmd.h"
//#include "usb_input.h"
#include "usb_output.h"
#include "serial.h"
#include "tty.h"
#include "beacon.h"
#define TIME_10MS (10 * 1000) // 10 ms = 10 * 1000 us
// greeting message
static const uint8_t greeting[] =
"\r\nJN1DFF MODELESS TNC V 1.00\r\n"
"Type HELP for Info\r\n"
"\r\n"
"cmd: ";
int main()
{
stdio_init_all();
if (watchdog_caused_reboot()) {
printf("Watch Dog Timer Failure\n");
}
// create usb output queue
usb_output_init();
// initialize tnc
tnc_init();
send_init();
receive_init();
serial_init();
tty_init(); // should call after tnc_init()
//bell202_init();
#ifdef TEST_PACKET
//test_init((1 << PORT_N) - 1); // test packet for all port
test_init(1); // only port 0
#endif
#ifdef BUSY_PIN
gpio_init(BUSY_PIN);
gpio_set_dir(BUSY_PIN, true); // output
#endif
#define SMPS_PIN 23
#if 1
gpio_init(SMPS_PIN);
gpio_set_dir(SMPS_PIN, true); // output
gpio_put(SMPS_PIN, 0);
#endif
// output greeting text
tty_write_str(&tty[0], greeting);
tty_write_str(&tty[1], greeting);
//uint32_t ts = time_us_32();
// set watchdog, timeout 1000 ms
watchdog_enable(1000, true);
// main loop
while (1) {
// update watchdog timer
watchdog_update();
#if 0
// advance tnc time
if (time_us_32() - ts >= TIME_10MS) {
++tnc_time;
ts += TIME_10MS;
}
#endif
// receive packet
receive();
// send packet
send();
// incoming KISS frame to serial
//kiss_input();
// output KISS frame to serial
//kiss_output();
// process uart I/O
serial_input();
serial_output();
#ifdef TEST_PACKET
// send test packet
test();
#endif
// send beacon
beacon();
#ifdef BUSY_PIN
// gpio_put(BUSY_PIN, 0);
#endif
// wait small time
__wfi();
#ifdef BUSY_PIN
// gpio_put(BUSY_PIN, 1);
#endif
}
return 0;
}

Plik diff jest za duży Load Diff

Wyświetl plik

@ -0,0 +1,30 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
extern const unsigned char packet_table[];
extern const int packet_table_size;

249
pico_tnc/receive.c 100644
Wyświetl plik

@ -0,0 +1,249 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "pico/stdlib.h"
// For ADC input:
#include "hardware/adc.h"
#include "hardware/dma.h"
#include "hardware/pwm.h"
#include "hardware/irq.h"
#include "pico/sem.h"
#include "hardware/watchdog.h"
// For resistor DAC output:
//#include "pico/multicore.h"
//#include "hardware/pio.h"
//#include "resistor_dac.pio.h"
#include "tnc.h"
#include "decode.h"
#include "bell202.h"
//#include "timer.h"
// Channel 0 is GPIO26
#define ADC_GPIO 26
#define BUF_NUM 16
#define BUF_LEN ((BAUD_RATE * SAMPLING_N * PORT_N + 50) / 100) // ADC samples in 10 ms
#define DEBUG_PIN 22
#if ADC_BIT == 8
static uint8_t buf[BUF_NUM][BUF_LEN];
#else
static uint16_t buf[BUF_NUM][BUF_LEN];
#endif
// DMA channel for ADC
static int dma_chan;
static semaphore_t sem;
static void dma_handler(void) {
static int buf_next = 1;
#if 0
if (sem_available(&sem) == BUF_NUM) {
printf("ADC: DMA buffer overrun\n");
assert(false);
}
#endif
// set buffer address
dma_channel_set_write_addr(dma_chan, buf[buf_next], true); // trigger DMA
// release semaphore
sem_release(&sem);
// advance ADC buffer
++buf_next;
buf_next &= BUF_NUM - 1;
// clear the interrupt request, ADC DMA using irq1
dma_hw->ints1 = dma_hw->ints1;
}
static const uint8_t cdt_pins[] = {
#ifdef PICO_DEFAULT_LED_PIN
PICO_DEFAULT_LED_PIN,
#else
20, // port 0
#endif
21, // port 1
22, // port 2
22, // dummy
22, // dummy
};
void receive_init(void)
{
// Init GPIO for analogue use: hi-Z, no pulls, disable digital input buffer.
uint8_t adc_rr_mask = 0;
for (int i = 0; i < PORT_N; i++) {
// initialize GPIO pin for ADC
int adc_pin = ADC_GPIO + i;
adc_gpio_init(adc_pin);
adc_rr_mask |= 1 << i;
tnc_t *tp = &tnc[i];
// set cdt led pin
uint8_t pin = cdt_pins[i];
gpio_init(pin);
gpio_set_dir(pin, GPIO_OUT);
tp->cdt_pin = pin;
// initialize variables
tp->cdt = false;
tp->cdt_lvl = 0;
tp->avg = 0;
}
adc_init();
adc_select_input(0); // start at ADC 0
adc_set_round_robin(adc_rr_mask);
adc_fifo_setup(
true, // Write each completed conversion to the sample FIFO
true, // Enable DMA data request (DREQ)
1, // DREQ (and IRQ) asserted when at least 1 sample present
false, // We won't see the ERR bit because of 8 bit reads; disable.
#if ADC_BIT == 8
true // Shift each sample to 8 bits when pushing to FIFO
#else
false // ADC sample 12 bits
#endif
);
#define ADC_CLK (48ULL * 1000 * 1000)
adc_hw->div = (ADC_CLK * 256 + ADC_SAMPLING_RATE/2) / ADC_SAMPLING_RATE - 256; // (INT part - 1) << 8 | FRAC part
//
//printf("adc.div = 0x%x, freq. = %f Hz\n", adc_hw->div, 48e6 * 256 / (adc_hw->div + 256));
//sleep_ms(1000);
// Set up the DMA to start transferring data as soon as it appears in FIFO
dma_chan = dma_claim_unused_channel(true);
dma_channel_config cfg = dma_channel_get_default_config(dma_chan);
//printf("initialize DMA channel: %d\n", dma_chan);
// Reading from constant address, writing to incrementing byte addresses
#if ADC_BIT == 8
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
#else
channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16);
#endif
channel_config_set_read_increment(&cfg, false);
channel_config_set_write_increment(&cfg, true);
// Pace transfers based on availability of ADC samples
channel_config_set_dreq(&cfg, DREQ_ADC);
channel_config_set_enable(&cfg, true);
dma_channel_configure(dma_chan, &cfg,
buf[0], // dst
&adc_hw->fifo, // src
BUF_LEN, // transfer count
false // start immediately
);
// DMA irq
dma_channel_set_irq1_enabled(dma_chan, true);
irq_set_exclusive_handler(DMA_IRQ_1, dma_handler);
irq_set_priority(DMA_IRQ_1, 0x40); // high priority
irq_set_enabled(DMA_IRQ_1, true);
// initialize semaphore
sem_init(&sem, 0, BUF_NUM);
//tnc_init();
//bell202_init();
// DMA start
dma_channel_start(dma_chan);
// ADC start
adc_run(true);
}
void receive(void)
{
static int buf_next = 0;
static uint8_t port = 0;
// wait for ADC samples
if (!sem_acquire_timeout_ms(&sem, 0)) return;
#ifdef BUSY_PIN
gpio_put(BUSY_PIN, 1);
#endif
++__tnc_time; // advance 10ms timer
// process adc data
for (int i = 0; i < BUF_LEN; i++) {
int val = buf[buf_next][i];
tnc_t *tp = &tnc[port];
if (++port >= PORT_N) port = 0; // ADC ch round robin
// decode Bell202
#if 0
#if ADC_BIT == 8
demodulator(tp, val - 128);
#else
demodulator(tp, val - 2048);
#endif
#else
demodulator(tp, val); // pass raw value
#endif
}
// advance next buffer
++buf_next;
buf_next &= BUF_NUM - 1;
#ifdef BUSY_PIN
gpio_put(BUSY_PIN, 0);
#endif
}
void receive_off(void)
{
adc_run(false);
}
void receive_on(void)
{
adc_run(true);
}

32
pico_tnc/receive.h 100644
Wyświetl plik

@ -0,0 +1,32 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
void receive_init(void);
void receive(void);
void receive_off(void);
void receive_on(void);

452
pico_tnc/send.c 100644
Wyświetl plik

@ -0,0 +1,452 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* send.c - send packet
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "pico/stdlib.h"
#include "hardware/dma.h"
#include "hardware/pwm.h"
#include "hardware/irq.h"
#include "hardware/sync.h"
#include "hardware/structs/uart.h"
#include "pico/util/queue.h"
#include "tnc.h"
#include "send.h"
#include "ax25.h"
//#include "wave_table.h"
#include "wave_table_132mhz.h"
static const int pwm_pins[] = {
14, // port 0
12,
10,
8,
6,
4,
2,
0
};
static const int ptt_pins[] = {
//PICO_DEFAULT_LED_PIN
15, // port 0
13,
11,
9,
7,
5,
3,
1
};
#define LED_PIN PICO_DEFAULT_LED_PIN
#define ISR_PIN 15
static void __isr dma_handler(void)
{
int int_status = dma_hw->ints0;
//printf("irq: %08x\n", dma_hw->ints0);
for (int i = 0; i < PORT_N; i++) {
tnc_t *tp = &tnc[i];
if (int_status & tp->data_chan_mask) {
// generate modem signal
uint32_t *addr;
if (queue_try_remove(&tp->dac_queue, &addr)) {
dma_channel_set_read_addr(tp->ctrl_chan, addr, true);
#if 0
printf("dma_hander: block = %p\n", &block[0]);
for (int i = 0; i < CONTROL_N + 1; i++) {
printf("block[%d] = %p\n", i, block[i]);
}
#endif
} else {
gpio_put(tp->ptt_pin, 0); // PTT off
pwm_set_chan_level(tp->pwm_slice, PWM_CHAN_A, 0); // set pwm level 0
tp->busy = false;
//printf("(%u) dma_handler: queue is empty, port = %d, data_chan = %d, ints = %08x\n", tnc_time(), tp->port, tp->data_chan, int_status);
}
//dma_hw->ints0 = tp->data_chan_mask;
}
} // for
dma_hw->ints0 = int_status;
}
static void send_start(tnc_t *tp)
{
if (!tp->busy) {
gpio_put(tp->ptt_pin, 1); // PTT on
tp->busy = true;
//printf("restart dma, ctrl = %08x, port = %d\n", dma_hw->ch[tp->data_chan].ctrl_trig, tp->port);
dma_channel_set_read_addr(tp->data_chan, NULL, true);
}
}
bool send_packet(tnc_t *tp, uint8_t *data, int len)
{
int length = len + 2; // fcs 2 byte
uint8_t byte;
if (send_queue_free(tp) < length + 2) return false; // queue has no room
// packet length
byte = length;
queue_try_add(&tp->send_queue, &byte);
byte = length >> 8;
queue_try_add(&tp->send_queue, &byte);
// send packet to queue
for (int i = 0; i < len; i++) {
queue_try_add(&tp->send_queue, &data[i]);
}
int fcs = ax25_fcs(0, data, len);
// fcs
byte = fcs;
queue_try_add(&tp->send_queue, &byte);
byte = fcs >> 8;
queue_try_add(&tp->send_queue, &byte);
return true;
}
int send_byte(tnc_t *tp, uint8_t data, bool bit_stuff)
{
int idx = 0;
// generate modem signal
if (!queue_is_full(&tp->dac_queue)) {
//uint8_t data = rand();
int byte = data | 0x100; // sentinel
int bit = byte & 1;
while (byte > 1) { // check sentinel
if (!bit) tp->level ^= 1; // NRZI, invert if original bit == 0
// make Bell202 CPAFSK audio samples
tp->dma_blocks[tp->next][idx++] = phase_tab[tp->level][tp->phase]; // 1: mark, 0: space
if (!tp->level) { // need adjust phase if space (2200Hz)
if (--tp->phase < 0) tp->phase = PHASE_CYCLE - 1;
}
// bit stuffing
if (bit_stuff) {
if (bit) {
if (++tp->cnt_one >= BIT_STUFF_BITS) {
// insert "0" bit
bit = 0;
continue; // while
}
} else {
tp->cnt_one = 0;
}
}
byte >>= 1;
bit = byte & 1;
}
// insert DMA end mark
tp->dma_blocks[tp->next][idx] = NULL;
// send fsk data to dac queue
uint16_t const **block = &tp->dma_blocks[tp->next][0];
if (queue_try_add(&tp->dac_queue, &block)) {
#if 0
if (!tp->busy) {
tp->busy = true;
dma_channel_set_read_addr(tp->data_chan, NULL, true);
//printf("restart dma, ctrl = %08x, port = %d\n", dma_hw->ch[tp->data_chan].ctrl_trig, tp->port);
}
#endif
if (++tp->next >= DAC_BLOCK_LEN) tp->next = 0;
//printf("main: queue add success\n");
} else {
printf("main: queue add fail\n");
}
} else {
send_start(tp);
}
return idx;
}
void send_init(void)
{
// set system clock, PWM uses system clock
set_sys_clock_khz(SYS_CLK_KHZ, true);
// initialize tnc[]
for (int i = 0; i < PORT_N; i++) {
tnc_t *tp = &tnc[i];
// port No.
tp->port = i;
// queue
queue_init(&tp->dac_queue, sizeof(uint32_t *), DAC_QUEUE_LEN);
// PTT pins
tp->ptt_pin = ptt_pins[i];
gpio_init(tp->ptt_pin);
gpio_set_dir(tp->ptt_pin, true); // output
gpio_put(tp->ptt_pin, 0);
// PWM pins
tp->pwm_pin = pwm_pins[i];
// PWM configuration
gpio_set_function(tp->pwm_pin, GPIO_FUNC_PWM);
// PWM slice
tp->pwm_slice = pwm_gpio_to_slice_num(tp->pwm_pin);
// PWM configuration
pwm_config pc = pwm_get_default_config();
pwm_config_set_clkdiv_int(&pc, 1); // 1.0
pwm_config_set_wrap(&pc, PWM_CYCLE - 1);
pwm_init(tp->pwm_slice, &pc, true); // start PWM
// DMA
tp->ctrl_chan = dma_claim_unused_channel(true);
tp->data_chan = dma_claim_unused_channel(true);
tp->data_chan_mask = 1 << tp->data_chan;
//printf("port %d: pwm_pin = %d, ptt_pin = %d, ctrl_chan = %d, data_chan = %d\n", tp->port, tp->pwm_pin, tp->ptt_pin, tp->ctrl_chan, tp->data_chan);
// DMA control channel
dma_channel_config dc = dma_channel_get_default_config(tp->ctrl_chan);
channel_config_set_transfer_data_size(&dc, DMA_SIZE_32);
channel_config_set_read_increment(&dc, true);
channel_config_set_write_increment(&dc, false);
dma_channel_configure(
tp->ctrl_chan,
&dc,
&dma_hw->ch[tp->data_chan].al3_read_addr_trig, // Initial write address
NULL, // Initial read address
1, // Halt after each control block
false // Don't start yet
);
// DMA data channel
dc = dma_channel_get_default_config(tp->data_chan);
channel_config_set_transfer_data_size(&dc, DMA_SIZE_16); // PWM level is 16 bits
channel_config_set_dreq(&dc, DREQ_PWM_WRAP0 + tp->pwm_slice);
channel_config_set_chain_to(&dc, tp->ctrl_chan);
channel_config_set_irq_quiet(&dc, true);
// set high priority bit
//dc.ctrl |= DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS;
dma_channel_configure(
tp->data_chan,
&dc,
&pwm_hw->slice[tp->pwm_slice].cc,
NULL, // Initial read address and transfer count are unimportant;
BIT_CYCLE, // audio data of 1/1200 s
false // Don't start yet.
);
// configure IRQ
dma_channel_set_irq0_enabled(tp->data_chan, true);
}
// configure IRQ
irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
//irq_add_shared_handler(DMA_IRQ_0, dma_handler, PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY);
irq_set_enabled(DMA_IRQ_0, true);
// ISR time measurement
gpio_init(ISR_PIN);
gpio_set_dir(ISR_PIN, true);
#define SMPS_PIN 23
// SMPS set PWM mode
gpio_init(SMPS_PIN);
gpio_set_dir(SMPS_PIN, true);
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)
{
return SEND_QUEUE_LEN - queue_get_level(&tp->send_queue);
}
void send(void)
{
uint8_t data;
tnc_t *tp = &tnc[0];
while (tp < &tnc[PORT_N]) {
switch (tp->send_state) {
case SP_IDLE:
//printf("(%d) send: SP_IDEL\n", tnc_time());
if (!queue_is_empty(&tp->send_queue)) {
tp->send_state = SP_WAIT_CLR_CH;
continue;
}
break;
case SP_WAIT_CLR_CH:
//printf("(%d) send: SP_WAIT_CLR_CH\n", tnc_time());
if (tp->kiss_fullduplex || !tp->cdt) {
tp->send_state = SP_P_PERSISTENCE;
continue;
}
break;
case SP_P_PERSISTENCE:
data = rand();
//printf("(%d) send: SP_P_PERSISTENCE, rnd = %d\n", tnc_time(), data);
if (data <= tp->kiss_p) {
tp->send_state = SP_PTT_ON;
continue;
}
tp->send_time = tnc_time();
tp->send_state = SP_WAIT_SLOTTIME;
break;
case SP_WAIT_SLOTTIME:
//printf("(%d) send: SP_WAIT_SLOTTIME\n", tnc_time());
if (tnc_time() - tp->send_time >= tp->kiss_slottime) {
tp->send_state = SP_WAIT_CLR_CH;
continue;
}
break;
case SP_PTT_ON:
//printf("(%d) send: SP_PTT_ON\n", tnc_time());
//gpio_put(tp->ptt_pin, 1);
tp->send_len = (tp->kiss_txdelay * 3) / 2 + 1; // TXDELAY * 10 [ms] into number of flags
tp->send_state = SP_SEND_FLAGS;
/* FALLTHROUGH */
case SP_SEND_FLAGS:
//printf("(%d) send: SP_SEND_FLAGS\n", tnc_time());
while (tp->send_len > 0 && send_byte(tp, AX25_FLAG, false)) { // false: bit stuffing off
--tp->send_len;
}
if (tp->send_len > 0) break;
tp->cnt_one = 0; // bit stuffing counter clear
tp->send_state = SP_DATA_START;
/* FALLTHROUGH */
case SP_DATA_START:
if (!queue_try_remove(&tp->send_queue, &data)) {
tp->send_state = SP_IDLE;
break;
}
// read packet length low byte
tp->send_len = data;
if (!queue_try_remove(&tp->send_queue, &data)) {
printf("send: send_queue underrun, len\n");
tp->send_state = SP_IDLE;
break;
}
// read packet length high byte
tp->send_len += data << 8;
//printf("(%d) send: SP_DATA_START, len = %d\n", tnc_time(), tp->send_len);
if (!queue_try_remove(&tp->send_queue, &data)) {
printf("send: send_queue underrun, data(1)\n");
tp->send_state = SP_IDLE;
break;
}
tp->send_data = data;
--tp->send_len;
tp->send_state = SP_DATA;
/* FALLTHROUGH */
case SP_DATA:
//printf("(%d) send: SP_DATA\n", tnc_time());
if (!send_byte(tp, tp->send_data, true)) break;
if (tp->send_len <= 0) {
tp->send_len = 1;
tp->send_state = SP_SEND_FLAGS;
send_start(tp);
continue;
}
if (!queue_try_remove(&tp->send_queue, &data)) {
printf("send: send_queue underrun, data(2)\n");
tp->send_state = SP_IDLE;
break;
}
--tp->send_len;
tp->send_data = data;
continue;
case SP_ERROR:
//printf("(%d) send: SP_ERROR\n", tnc_time());
while (queue_try_remove(&tp->send_queue, &data)) {
}
tp->send_state = SP_IDLE;
}
tp++;
} // while
}

41
pico_tnc/send.h 100644
Wyświetl plik

@ -0,0 +1,41 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
/*
send.h
*/
#include "tnc.h"
#define BYTE_BITS 8
#define BIT_STUFF_BITS 5
int send_byte(tnc_t *tp, uint8_t data, bool bit_stuff);
void send_init(void);
void send(void);
int send_queue_free(tnc_t *tp);
bool send_packet(tnc_t *tp, uint8_t *data, int len);

127
pico_tnc/serial.c 100644
Wyświetl plik

@ -0,0 +1,127 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/uart.h"
#include "pico/util/queue.h"
#include "tnc.h"
#include "tty.h"
#include "gps.h"
#define UART_BAUDRATE 115200
#define UART_QUEUE_LEN 1024
#define GPS_ENABLE 1
#define GPS_BAUDRATE 9600
static queue_t uart_queue;
void serial_init(void)
{
queue_init(&uart_queue, sizeof(uint8_t), UART_QUEUE_LEN);
assert(uart_queue != NULL);
uint baud = uart_init(uart0, UART_BAUDRATE);
//printf("UART0 baud rate = %u\n", baud);
uart_set_fifo_enabled(uart0, true);
gpio_set_function(0, GPIO_FUNC_UART);
gpio_set_function(1, GPIO_FUNC_UART);
#ifdef GPS_ENABLE
// GPS
baud = uart_init(uart1, GPS_BAUDRATE);
//printf("UART1 baud rate = %u\n", baud);
uart_set_fifo_enabled(uart0, true);
gpio_set_function(4, GPIO_FUNC_UART);
gpio_set_function(5, GPIO_FUNC_UART);
#endif
}
void serial_write(uint8_t const *data, int len)
{
int free = UART_QUEUE_LEN - queue_get_level(&uart_queue);
for (int i = 0; i < len && i < free; i++) {
if (!queue_try_add(&uart_queue, &data[i])) break;
}
}
void serial_write_char(uint8_t ch)
{
queue_try_add(&uart_queue, &ch);
}
void serial_output(void)
{
if (queue_is_empty(&uart_queue)) return;
while (uart_is_writable(uart0)) {
uint8_t ch;
if (!queue_try_remove(&uart_queue, &ch)) break;
uart_putc_raw(uart0, ch);
}
}
void serial_input(void)
{
#ifdef GPS_ENABLE
while (uart_is_readable(uart1)) {
int ch = uart_getc(uart1);
gps_input(ch);
}
#endif
while (uart_is_readable(uart0)) {
int ch = uart_getc(uart0);
tty_input(&tty[TTY_UART0], ch);
}
#if 0
switch (ch) {
case 0x08:
case 0x7f:
uart_puts(uart0, "\b \b");
break;
case 0x0d:
uart_puts(uart0, "\r\n");
break;
default:
uart_putc_raw(uart0, ch);
}
#endif
}

34
pico_tnc/serial.h 100644
Wyświetl plik

@ -0,0 +1,34 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
void serial_init(void);
void serial_input(void);
void serial_write(uint8_t const *data, int len);
void serial_write_char(uint8_t ch);
void serial_output(void);

162
pico_tnc/test.c 100644
Wyświetl plik

@ -0,0 +1,162 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "tnc.h"
#include "packet_table.h"
#include "ax25.h"
enum TEST_STATE {
TEST_IDLE = 0,
TEST_PACKET_START,
TEST_WAIT,
TEST_ERROR,
};
#if 0
static int test_state = TEST_IDLE;
static const uint8_t *ptp = packet_table;
static const uint8_t *packet;
static uint16_t packet_len;
static int wait_time;
#endif
#define SEND_INTERVAL (30 * 100) // interval 10 ms unit
#define SLEEP (10 * 100) // wait time when buffer full
#define MAX_SLEEP (~0) // int max
static int port_mask = 0;
void test_init(int mask)
{
port_mask = mask & ((1 << PORT_N) - 1);
for (int port = 0; port < PORT_N; port++) {
if (!(port_mask & (1 << port))) continue;
tnc_t *tp = &tnc[port];
tp->test_state = TEST_IDLE;
tp->ptp = packet_table;
}
}
void test(void)
{
uint8_t data;
uint16_t fcs;
//if (port < 0 || port >= PORT_N) return;
for (int port = 0; port < PORT_N; port++) {
if (!(port_mask & (1 << port))) continue;
tnc_t *tp = &tnc[port];
switch (tp->test_state) {
case TEST_IDLE:
//printf("(%d) test: TEST_IDLE\n", tnc_time());
tp->packet_len = *tp->ptp++;
if (tp->packet_len == 0) {
#if 0
printf("test: send all packets, stop\n");
wait_time = MAX_SLEEP;
test_state = TEST_WAIT;
break;
#else
printf("(%u) test: send all test packets done, port = %d\n", tnc_time(), tp->port);
tp->ptp = packet_table;
tp->packet_len = *tp->ptp++;
#endif
}
//printf("(%d) test: test packet\n", tnc_time());
tp->packet = tp->ptp;
tp->ptp += tp->packet_len;
tp->test_state = TEST_PACKET_START;
/* FALLTHROUGH */
case TEST_PACKET_START:
//printf("(%d) test: TEST_PACKET_START\n", tnc_time());
if (SEND_QUEUE_LEN - queue_get_level(&tp->send_queue) < tp->packet_len + 2) { // "2" means length field (16bit)
//printf("(%u) test: send_queue is full, port = %d\n", tnc_time(), tp->port);
break;
}
// packet length
for (int i = 0; i < 2; i++) {
data = tp->packet_len >> (i * 8);
if (!queue_try_add(&tp->send_queue, &data)) {
tp->test_state = TEST_ERROR;
break;
}
}
#define CALC_FCS 1
// packet data
#ifdef CALC_FCS
for (int i = 0; i < tp->packet_len - 2; i++) {
#else
for (int i = 0; i < tp->packet_len; i++) {
#endif
if (!queue_try_add(&tp->send_queue, &tp->packet[i])) {
tp->test_state = TEST_ERROR;
break;
}
}
#ifdef CALC_FCS
// fcs
fcs = ax25_fcs(0, tp->packet, tp->packet_len - 2);
// add fcs
for (int i = 0; i < 2; i++) {
data = fcs >> (i * 8);
if (!queue_try_add(&tp->send_queue, &data)) {
tp->test_state = TEST_ERROR;
break;
}
}
#endif
tp->wait_time = tnc_time();
tp->test_state = TEST_WAIT;
break;
case TEST_WAIT:
//printf("(%d) test: TEST_WAIT\n", tnc_time());
if (tnc_time() - tp->wait_time < SEND_INTERVAL) break;
tp->test_state = TEST_IDLE;
break;
case TEST_ERROR:
printf("(%d) test: TEST_ERROR\n", tnc_time());
printf("test: error occured, stop\n");
tp->wait_time = MAX_SLEEP;
tp->test_state = TEST_WAIT;
}
}
}

30
pico_tnc/test.h 100644
Wyświetl plik

@ -0,0 +1,30 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
void test_init(int mask);
void test(void);

116
pico_tnc/tnc.c 100644
Wyświetl plik

@ -0,0 +1,116 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "tnc.h"
#include "ax25.h"
#include "flash.h"
uint32_t __tnc_time;
tnc_t tnc[PORT_N];
param_t param = {
.mycall = { 0, 0, },
.unproto = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, },
.myalias = { 0, 0 },
.btext = "",
.txdelay = 100,
.echo = 1,
.gps = 0,
.trace = 0,
.mon = 0,
.digi = 0,
.beacon = 0,
};
void tnc_init(void)
{
// filter initialization
// LPF
static const filter_param_t flt_lpf = {
.size = FIR_LPF_N,
.sampling_freq = SAMPLING_RATE,
.pass_freq = 0,
.cutoff_freq = 1200,
};
int16_t *lpf_an, *bpf_an;
lpf_an = filter_coeff(&flt_lpf);
#if 0
printf("LPF coeffient\n");
for (int i = 0; i < flt_lpf.size; i++) {
printf("%d\n", lpf_an[i]);
}
#endif
// BPF
static const filter_param_t flt_bpf = {
.size = FIR_BPF_N,
.sampling_freq = SAMPLING_RATE,
.pass_freq = 900,
.cutoff_freq = 2500,
};
bpf_an = filter_coeff(&flt_bpf);
#if 0
printf("BPF coeffient\n");
for (int i = 0; i < flt_bpf.size; i++) {
printf("%d\n", bpf_an[i]);
}
#endif
// PORT initialization
for (int i = 0; i < PORT_N; i++) {
tnc_t *tp = &tnc[i];
// receive
tp->port = i;
tp->state = FLAG;
filter_init(&tp->lpf, lpf_an, FIR_LPF_N);
filter_init(&tp->bpf, bpf_an, FIR_BPF_N);
// send queue
queue_init(&tp->send_queue, sizeof(uint8_t), SEND_QUEUE_LEN);
tp->cdt = 0;
tp->kiss_txdelay = 50;
tp->kiss_p = 63;
tp->kiss_slottime = 10;
tp->kiss_fullduplex = 0;
}
//printf("%d ports support\n", PORT_N);
//printf("DELAYED_N = %d\n", DELAYED_N);
// read flash
flash_read(&param, sizeof(param));
// set kiss txdelay
if (param.txdelay > 0) {
tnc[0].kiss_txdelay = param.txdelay * 2 / 3;
}
}

258
pico_tnc/tnc.h 100644
Wyświetl plik

@ -0,0 +1,258 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "pico/util/queue.h"
#include "filter.h"
#include "ax25.h"
//#include "cmd.h"
// number of ports
#define PORT_N 1 // number of ports, 1..3
#define BAUD_RATE 1200
#define SAMPLING_N 11
//#define DELAY_N 3
//#define SAMPLING_RATE ((1000000*DELAY_N+DELAY_US/2)/DELAY_US)
#define SAMPLING_RATE (BAUD_RATE * SAMPLING_N)
#define DELAY_US 446 // 446us
#define DELAYED_N ((SAMPLING_RATE * DELAY_US + 500000) / 1000000)
#define ADC_SAMPLING_RATE (SAMPLING_RATE * PORT_N)
#define DATA_LEN 1024 // packet receive buffer size
#define FIR_LPF_N 27
#define FIR_BPF_N 25
#define ADC_BIT 8 // adc bits 8 or 12
//#define ADC_BIT 12 // adc bits 8 or 12
//#define BELL202_SYNC 1 // sync decode
#define DECODE_PLL 1 // use PLL
#define CONTROL_N 10
#define DAC_QUEUE_LEN 64
#define DAC_BLOCK_LEN (DAC_QUEUE_LEN + 1)
#define SEND_QUEUE_LEN (1024 * 16)
#define AX25_FLAG 0x7e
#define BUSY_PIN 22
#define BEACON_PORT 0
#define KISS_PACKET_LEN 1024 // kiss packet length
#define TTY_N 3 // number of serial
#define CMD_BUF_LEN 255
enum STATE {
FLAG,
DATA
};
typedef struct {
int low_i;
int low_q;
int high_i;
int high_q;
} values_t;
typedef struct TNC {
uint8_t port;
// receive
// demodulator
uint8_t bit;
// decode_bit
uint16_t data_cnt;
uint8_t data[DATA_LEN];
uint8_t state;
uint8_t flag;
uint8_t data_byte;
uint8_t data_bit_cnt;
// decode
uint8_t edge;
// decode2
int32_t pll_counter;
uint8_t pval;
uint8_t nrzi;
// output_packet
int pkt_cnt;
// bell202_decode
int delayed[DELAYED_N];
int delay_idx;
int cdt;
int cdt_lvl;
int avg;
uint8_t cdt_pin;
// bell202_decode2
int sum_low_i;
int sum_low_q;
int sum_high_i;
int sum_high_q;
int low_idx;
int high_idx;
values_t values[SAMPLING_N];
int values_idx;
filter_t lpf;
filter_t bpf;
// send
// kiss parameter
uint8_t kiss_txdelay;
uint8_t kiss_p;
uint8_t kiss_slottime;
uint8_t kiss_fullduplex;
// dac queue
queue_t dac_queue;
// DAC, PTT pin
uint8_t ptt_pin;
uint8_t pwm_pin;
uint8_t pwm_slice;
// DMA channels
uint8_t ctrl_chan;
uint8_t data_chan;
uint32_t data_chan_mask;
uint8_t busy;
// Bell202 wave generator
int next;
int phase;
int level;
int cnt_one;
// wave buffer for DMA
uint16_t const *dma_blocks[DAC_BLOCK_LEN][CONTROL_N + 1];
// send data queue
queue_t send_queue;
int send_time;
int send_len;
int send_state;
int send_data;
// field for test packet
int test_state;
uint8_t const *ptp;
uint8_t const *packet;
uint16_t packet_len;
int wait_time;
} tnc_t;
extern tnc_t tnc[];
extern uint32_t __tnc_time;
void tnc_init(void);
inline uint32_t tnc_time(void)
{
return __tnc_time;
}
// TNC command
enum MONITOR {
MON_ALL = 0,
MON_ME,
MON_OFF,
};
// GPS
enum GPS_SENTENCE {
GPGGA = 0,
GPGLL,
GPRMC,
};
#define UNPROTO_N 4
#define BTEXT_LEN 100
// TNC parameter
typedef struct TNC_PARAM {
callsign_t mycall;
callsign_t myalias;
callsign_t unproto[UNPROTO_N];
uint8_t btext[BTEXT_LEN + 1];
uint8_t txdelay;
uint8_t gps;
uint8_t mon;
uint8_t digi;
uint8_t beacon;
uint8_t trace;
uint8_t echo;
} param_t;
extern param_t param;
// tty
enum TTY_MODE {
TTY_TERMINAL = 0,
TTY_GPS,
};
enum TTY_SERIAL {
TTY_USB = 0,
TTY_UART0,
TTY_UART1,
};
typedef struct TTY {
uint8_t kiss_buf[KISS_PACKET_LEN];
uint8_t cmd_buf[CMD_BUF_LEN + 1];
int kiss_idx;
int cmd_idx;
uint8_t num; // index of tty[]
uint8_t tty_mode; // terminal or GPS
uint8_t tty_serial; // USB, UART0, UART1
uint8_t kiss_mode; // kiss mode
uint8_t kiss_state; // kiss state
uint32_t kiss_timeout; // kiss timer
tnc_t *tp; // input/output port No.
} tty_t;
extern tty_t tty[];

177
pico_tnc/tty.c 100644
Wyświetl plik

@ -0,0 +1,177 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "class/cdc/cdc_device.h"
#include "pico/sync.h"
#include "hardware/uart.h"
#include "tnc.h"
#include "cmd.h"
#include "usb_output.h"
#include "tnc.h"
#include "usb_input.h"
#include "serial.h"
#include "unproto.h"
#include "kiss.h"
#define CONVERSE_PORT 0
// usb echo flag
//uint8_t usb_echo = 1; // on
// tty info
tty_t tty[TTY_N];
//static uint8_t cmd_buf[CMD_LEN + 1];
//static int cmd_idx = 0;
static const enum TTY_MODE tty_mode[] = {
TTY_TERMINAL,
TTY_TERMINAL,
TTY_GPS,
};
static const enum TTY_SERIAL tty_serial[] = {
TTY_USB,
TTY_UART0,
TTY_UART1,
};
void tty_init(void)
{
for (int i = 0; i < TTY_N; i++) {
tty_t *ttyp = &tty[i];
ttyp->num = i;
ttyp->tty_mode = tty_mode[i];
ttyp->tty_serial = tty_serial[i];
ttyp->kiss_mode = false;
}
}
void tty_write(tty_t *ttyp, uint8_t const *data, int len)
{
if (ttyp->tty_serial == TTY_USB) {
usb_write(data, len);
return;
}
if (ttyp->tty_serial == TTY_UART0) serial_write(data, len);
}
void tty_write_char(tty_t *ttyp, uint8_t ch)
{
if (ttyp->tty_serial == TTY_USB) {
usb_write_char(ch);
return;
}
if (ttyp->tty_serial == TTY_UART0) serial_write_char(ch);
}
void tty_write_str(tty_t *ttyp, uint8_t const *str)
{
int len = strlen(str);
tty_write(ttyp, str, len);
}
#define BS '\b'
#define CR '\r'
#define DEL '\x7f'
#define BELL '\a'
#define CTRL_C '\x03'
#define FEND 0xc0
#define KISS_TIMEOUT (1 * 100) // 1 sec
void tty_input(tty_t *ttyp, int ch)
{
if (ttyp->kiss_state != KISS_OUTSIDE) {
// inside KISS frame
if (tnc_time() - ttyp->kiss_timeout < KISS_TIMEOUT) {
kiss_input(ttyp, ch);
return;
}
// timeout, exit kiss frame
ttyp->kiss_state = KISS_OUTSIDE;
}
switch (ch) {
case FEND: // KISS frame end
kiss_input(ttyp, ch);
break;
case BS:
case DEL:
if (ttyp->cmd_idx > 0) {
--ttyp->cmd_idx;
if (param.echo) tty_write_str(ttyp, "\b \b");
} else {
if (param.echo) tty_write_char(ttyp, BELL);
}
break;
case CR:
if (param.echo) tty_write_str(ttyp, "\r\n");
if (ttyp->cmd_idx > 0) {
ttyp->cmd_buf[ttyp->cmd_idx] = '\0';
if (converse_mode) {
send_unproto(&tnc[CONVERSE_PORT], ttyp->cmd_buf, ttyp->cmd_idx); // send UI packet
} else {
cmd(ttyp, ttyp->cmd_buf, ttyp->cmd_idx);
}
}
if (!converse_mode) tty_write_str(ttyp, "cmd: ");
ttyp->cmd_idx = 0;
break;
case CTRL_C:
if (converse_mode) {
converse_mode = false;
}
tty_write_str(ttyp, "\r\ncmd: ");
ttyp->cmd_idx = 0;
break;
default:
if ((ch >= ' ' && ch <= '~') && ttyp->cmd_idx < CMD_BUF_LEN) {
ttyp->cmd_buf[ttyp->cmd_idx++] = ch;
} else {
ch = BELL;
}
if (param.echo) tty_write_char(ttyp, ch);
}
}

38
pico_tnc/tty.h 100644
Wyświetl plik

@ -0,0 +1,38 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "tnc.h"
#include "kiss.h"
#include "cmd.h"
void tty_init(void);
void tty_input(tty_t *ttyp, int ch);
void tty_write(tty_t *ttyp, uint8_t const *data, int len);
void tty_write_char(tty_t *ttyp, uint8_t ch);
void tty_write_str(tty_t *ttyp, uint8_t const *str);

117
pico_tnc/unproto.c 100644
Wyświetl plik

@ -0,0 +1,117 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "tnc.h"
#include "ax25.h"
#include "send.h"
#define AX25_ADDR_LEN 7
static uint8_t addr[AX25_ADDR_LEN];
#define CON_PID_LEN 2
static const uint8_t con_pid[CON_PID_LEN] = { 0x03, 0xf0 }; // control, PID
void send_unproto(tnc_t *tp, uint8_t *data, int len)
{
uint8_t byte;
uint32_t fcs;
int repeaters = 0;
int i;
if (!param.mycall.call[0]) return; // no mycall
if (!param.unproto[0].call[0]) return; // no unproto
int pkt_len = AX25_ADDR_LEN * 2; // dst + src addr
// count repeaters
for (int i = 1; i < UNPROTO_N; i++) {
if (param.unproto[i].call[0]) { // exist repeater
pkt_len += AX25_ADDR_LEN;
repeaters++;
}
}
pkt_len += 2 + len + 2; // CONTL + PID + info + FCS
if (send_queue_free(tp) < pkt_len + 2) return;
// packet length
byte = pkt_len;
queue_try_add(&tp->send_queue, &byte);
byte = pkt_len >> 8;
queue_try_add(&tp->send_queue, &byte);
// dst addr
ax25_mkax25addr(addr, &param.unproto[0]);
addr[6] |= 0x80; // set C bit for AX.25 Ver2.2 Command
for (i = 0; i < AX25_ADDR_LEN; i++) {
queue_try_add(&tp->send_queue, &addr[i]);
}
fcs = ax25_fcs(0, addr, AX25_ADDR_LEN);
// src addr
ax25_mkax25addr(addr, &param.mycall);
if (repeaters == 0) addr[6] |= 1; // set address extension bit, if no repeaters
for (i = 0; i < AX25_ADDR_LEN; i++) {
queue_try_add(&tp->send_queue, &addr[i]);
}
fcs = ax25_fcs(fcs, addr, AX25_ADDR_LEN);
// repeaters
for (int j = 1; j <= repeaters; j++) {
if (param.unproto[j].call[0]) {
ax25_mkax25addr(addr, &param.unproto[j]);
if (j == repeaters) addr[6] |= 1; // set address extension bit, if last repeater
for (i = 0; i < AX25_ADDR_LEN; i++) {
queue_try_add(&tp->send_queue, &addr[i]);
}
fcs = ax25_fcs(fcs, addr, AX25_ADDR_LEN);
}
}
// control and PID
for (i = 0; i < CON_PID_LEN; i++) {
queue_try_add(&tp->send_queue, &con_pid[i]);
}
fcs = ax25_fcs(fcs, con_pid, CON_PID_LEN);
// info
for (i = 0; i < len; i++) {
queue_try_add(&tp->send_queue, &data[i]);
}
fcs = ax25_fcs(fcs, data, len);
// fcs
byte = fcs;
queue_try_add(&tp->send_queue, &byte);
byte = fcs >> 8;
queue_try_add(&tp->send_queue, &byte);
}

31
pico_tnc/unproto.h 100644
Wyświetl plik

@ -0,0 +1,31 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include "tnc.h"
void send_unproto(tnc_t *tp, uint8_t *data, int len);

Wyświetl plik

@ -0,0 +1,49 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "class/cdc/cdc_device.h"
#include "pico/sync.h"
#include "cmd.h"
#include "usb_output.h"
#include "tty.h"
#include "kiss.h"
// usb cdc callback function
void tud_cdc_rx_cb(uint8_t itf)
{
int len = tud_cdc_available();
for (int i = 0; i < len; i++) {
int ch = tud_cdc_read_char();
tty_input(&tty[TTY_USB], ch);
}
}

Wyświetl plik

@ -0,0 +1,32 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <stdio.h>
extern uint8_t usb_echo;
void usb_input(void);

Wyświetl plik

@ -0,0 +1,147 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "class/cdc/cdc_device.h"
#include "pico/sync.h"
#include "pico/util/queue.h"
#define QUEUE_SIZE 1024
static queue_t usb_queue;
void usb_output_init(void)
{
queue_init(&usb_queue, sizeof(uint8_t), QUEUE_SIZE);
assert(usb_queue != NULL);
}
void usb_write(uint8_t const *data, int len)
{
int i;
if (!queue_is_empty(&usb_queue)) {
for (i = 0; i < len; i++) {
if (!queue_try_add(&usb_queue, &data[i])) break;
}
return;
}
int free = tud_cdc_write_available();
if (free >= len) {
tud_cdc_write(data, len);
tud_cdc_write_flush();
return;
}
tud_cdc_write(data, free);
tud_cdc_write_flush();
for (i = free; i < len; i++) {
if (!queue_try_add(&usb_queue, &data[i])) break;
}
}
void usb_write_char(uint8_t ch)
{
int i = 0;
if (!queue_is_empty(&usb_queue)) {
queue_try_add(&usb_queue, &ch);
return;
}
if (tud_cdc_write_available() > 0) {
tud_cdc_write_char(ch);
tud_cdc_write_flush();
return;
}
queue_try_add(&usb_queue, &ch);
}
void usb_output(void)
{
uint8_t data;
if (queue_is_empty(&usb_queue)) return;
while (tud_cdc_write_available() > 0) {
if (queue_try_remove(&usb_queue, &data)) {
tud_cdc_write_char(data);
} else {
break;
}
}
tud_cdc_write_flush();
}
// TinyUSB callback function
void tud_cdc_tx_complete_cb(uint8_t itf)
{
uint8_t data;
if (queue_is_empty(&usb_queue)) return; // no queued data
int free = tud_cdc_write_available();
while (free > 0) {
if (!queue_try_remove(&usb_queue, &data)) break;
tud_cdc_write_char(data);
--free;
}
tud_cdc_write_flush();
}
#if 0
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char)
{
printf("tud_cdc_rx_wanted_cb(%d), wanted_char = %02x\n", itf, wanted_char);
}
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
{
printf("tud_cdc_line_state_cb(%d), dtr = %d, rts = %d\n", itf, dtr, rts);
}
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding)
{
printf("tud_cdc_line_coding_cb(%d), p_line_coding = %p\n", itf, p_line_coding);
}
void tud_cdc_send_break_cb(uint8_t itf, uint16_t duration_ms)
{
printf("tud_cdc_send_break_cb(%d), duration_ms = %u\n", itf, duration_ms);
}
#endif

Wyświetl plik

@ -0,0 +1,33 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
void usb_output_init(void);
void usb_output(void);
void usb_write(uint8_t const *data, int len);
void usb_write_char(uint8_t ch);

Wyświetl plik

@ -0,0 +1,141 @@
/*
Copyright (c) 2021, Kazuhisa Yokota, JN1DFF
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the <organization> nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
sine wave table for Bell202 FSK signal
*/
#define SYS_CLK_KHZ 132000
#define BIT_CYCLE 440
#define MARK_CYCLE 440
#define SPACE_CYCLE 240
#define MARK_TAB_LEN 807
#define SPACE_TAB_LEN 640
#define PHASE_CYCLE 6
#define PWM_CYCLE 250
static const uint16_t mark_tab[] = {
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xf9, 0xf9, 0xf9, 0xf9, 0xf8, 0xf8, 0xf8, 0xf8, 0xf7,
0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xef, 0xef, 0xee,
0xed, 0xec, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf,
0xde, 0xdd, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd5, 0xd4, 0xd3, 0xd2, 0xd0, 0xcf, 0xce, 0xcc, 0xcb,
0xc9, 0xc8, 0xc6, 0xc5, 0xc4, 0xc2, 0xc1, 0xbf, 0xbe, 0xbc, 0xba, 0xb9, 0xb7, 0xb6, 0xb4, 0xb3,
0xb1, 0xaf, 0xae, 0xac, 0xaa, 0xa9, 0xa7, 0xa5, 0xa4, 0xa2, 0xa0, 0x9f, 0x9d, 0x9b, 0x99, 0x98,
0x96, 0x94, 0x92, 0x91, 0x8f, 0x8d, 0x8b, 0x89, 0x88, 0x86, 0x84, 0x82, 0x81, 0x7f, 0x7d, 0x7b,
0x79, 0x78, 0x76, 0x74, 0x72, 0x71, 0x6f, 0x6d, 0x6b, 0x69, 0x68, 0x66, 0x64, 0x62, 0x61, 0x5f,
0x5d, 0x5b, 0x5a, 0x58, 0x56, 0x55, 0x53, 0x51, 0x50, 0x4e, 0x4c, 0x4b, 0x49, 0x47, 0x46, 0x44,
0x43, 0x41, 0x40, 0x3e, 0x3c, 0x3b, 0x39, 0x38, 0x36, 0x35, 0x34, 0x32, 0x31, 0x2f, 0x2e, 0x2c,
0x2b, 0x2a, 0x28, 0x27, 0x26, 0x25, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1d, 0x1c, 0x1b, 0x1a, 0x19,
0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0b,
0x0a, 0x09, 0x09, 0x08, 0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02,
0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05,
0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x20,
0x21, 0x22, 0x23, 0x25, 0x26, 0x27, 0x28, 0x2a, 0x2b, 0x2c, 0x2e, 0x2f, 0x31, 0x32, 0x34, 0x35,
0x36, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x40, 0x41, 0x43, 0x44, 0x46, 0x47, 0x49, 0x4b, 0x4c, 0x4e,
0x50, 0x51, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5b, 0x5d, 0x5f, 0x61, 0x62, 0x64, 0x66, 0x68, 0x69,
0x6b, 0x6d, 0x6f, 0x71, 0x72, 0x74, 0x76, 0x78, 0x79, 0x7b, 0x7d, 0x7f, 0x81, 0x82, 0x84, 0x86,
0x88, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x92, 0x94, 0x96, 0x98, 0x99, 0x9b, 0x9d, 0x9f, 0xa0, 0xa2,
0xa4, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xae, 0xaf, 0xb1, 0xb3, 0xb4, 0xb6, 0xb7, 0xb9, 0xba, 0xbc,
0xbe, 0xbf, 0xc1, 0xc2, 0xc4, 0xc5, 0xc6, 0xc8, 0xc9, 0xcb, 0xcc, 0xce, 0xcf, 0xd0, 0xd2, 0xd3,
0xd4, 0xd5, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5,
0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xec, 0xed, 0xee, 0xef, 0xef, 0xf0, 0xf1, 0xf1, 0xf2,
0xf3, 0xf3, 0xf4, 0xf4, 0xf5, 0xf5, 0xf6, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9,
0xf9, 0xf9, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xf9,
0xf9, 0xf9, 0xf9, 0xf8, 0xf8, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3,
0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xef, 0xef, 0xee, 0xed, 0xec, 0xec, 0xeb, 0xea, 0xe9, 0xe8, 0xe7,
0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0, 0xdf, 0xde, 0xdd, 0xdb, 0xda, 0xd9, 0xd8, 0xd7, 0xd5,
0xd4, 0xd3, 0xd2, 0xd0, 0xcf, 0xce, 0xcc, 0xcb, 0xc9, 0xc8, 0xc6, 0xc5, 0xc4, 0xc2, 0xc1, 0xbf,
0xbe, 0xbc, 0xba, 0xb9, 0xb7, 0xb6, 0xb4, 0xb3, 0xb1, 0xaf, 0xae, 0xac, 0xaa, 0xa9, 0xa7, 0xa5,
0xa4, 0xa2, 0xa0, 0x9f, 0x9d, 0x9b, 0x99, 0x98, 0x96, 0x94, 0x92, 0x91, 0x8f, 0x8d, 0x8b, 0x89,
0x88, 0x86, 0x84, 0x82, 0x81, 0x7f, 0x7d, 0x7b, 0x79, 0x78, 0x76, 0x74, 0x72, 0x71, 0x6f, 0x6d,
0x6b, 0x69, 0x68, 0x66, 0x64, 0x62, 0x61, 0x5f, 0x5d, 0x5b, 0x5a, 0x58, 0x56, 0x55, 0x53, 0x51,
0x50, 0x4e, 0x4c, 0x4b, 0x49, 0x47, 0x46, 0x44, 0x43, 0x41, 0x40, 0x3e, 0x3c, 0x3b, 0x39, 0x38,
0x36, 0x35, 0x34, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b, 0x2a, 0x28, 0x27, 0x26, 0x25, 0x23, 0x22,
0x21, 0x20, 0x1f, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
0x10, 0x0f, 0x0e, 0x0e, 0x0d, 0x0c, 0x0b, 0x0b, 0x0a, 0x09, 0x09, 0x08, 0x07, 0x07, 0x06, 0x06,
0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09,
0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x25, 0x26, 0x27, 0x28, 0x2a,
0x2b, 0x2c, 0x2e, 0x2f, 0x31, 0x32, 0x34, 0x35, 0x36, 0x38, 0x39, 0x3b, 0x3c, 0x3e, 0x40, 0x41,
0x43, 0x44, 0x46, 0x47, 0x49, 0x4b, 0x4c, 0x4e, 0x50, 0x51, 0x53, 0x55, 0x56, 0x58, 0x5a, 0x5b,
0x5d, 0x5f, 0x61, 0x62, 0x64, 0x66, 0x68, 0x69, 0x6b, 0x6d, 0x6f, 0x71, 0x72, 0x74, 0x76, 0x78,
0x79, 0x7b, 0x7d, 0x7f, 0x81, 0x82, 0x84, 0x86, 0x88, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x92, 0x94,
0x96, 0x98, 0x99, 0x9b, 0x9d, 0x9f, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xae, 0xaf,
0xb1, 0xb3, 0xb4, 0xb6, 0xb7, 0xb9, 0xba,
};
static const uint16_t space_tab[] = {
0xfa, 0xfa, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf0,
0xef, 0xee, 0xec, 0xeb, 0xe9, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, 0xde, 0xdc, 0xda, 0xd8, 0xd5, 0xd3,
0xd1, 0xce, 0xcc, 0xc9, 0xc6, 0xc4, 0xc1, 0xbe, 0xbc, 0xb9, 0xb6, 0xb3, 0xb0, 0xad, 0xaa, 0xa7,
0xa4, 0xa1, 0x9d, 0x9a, 0x97, 0x94, 0x91, 0x8d, 0x8a, 0x87, 0x84, 0x80, 0x7d, 0x7a, 0x76, 0x73,
0x70, 0x6d, 0x69, 0x66, 0x63, 0x60, 0x5d, 0x59, 0x56, 0x53, 0x50, 0x4d, 0x4a, 0x47, 0x44, 0x41,
0x3f, 0x3c, 0x39, 0x36, 0x34, 0x31, 0x2e, 0x2c, 0x29, 0x27, 0x25, 0x22, 0x20, 0x1e, 0x1c, 0x1a,
0x18, 0x16, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x11, 0x12, 0x14, 0x16,
0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x25, 0x27, 0x29, 0x2c, 0x2e, 0x31, 0x34, 0x36, 0x39, 0x3c,
0x3e, 0x41, 0x44, 0x47, 0x4a, 0x4d, 0x50, 0x53, 0x56, 0x59, 0x5d, 0x60, 0x63, 0x66, 0x69, 0x6d,
0x70, 0x73, 0x76, 0x7a, 0x7d, 0x80, 0x84, 0x87, 0x8a, 0x8d, 0x91, 0x94, 0x97, 0x9a, 0x9d, 0xa1,
0xa4, 0xa7, 0xaa, 0xad, 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbe, 0xc1, 0xc4, 0xc6, 0xc9, 0xcc, 0xce,
0xd1, 0xd3, 0xd5, 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xe9, 0xeb, 0xec, 0xee,
0xef, 0xf0, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
0xfa, 0xfa, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf0,
0xef, 0xee, 0xec, 0xeb, 0xe9, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, 0xde, 0xdc, 0xda, 0xd8, 0xd5, 0xd3,
0xd1, 0xce, 0xcc, 0xc9, 0xc6, 0xc4, 0xc1, 0xbe, 0xbc, 0xb9, 0xb6, 0xb3, 0xb0, 0xad, 0xaa, 0xa7,
0xa4, 0xa1, 0x9d, 0x9a, 0x97, 0x94, 0x91, 0x8d, 0x8a, 0x87, 0x84, 0x80, 0x7d, 0x7a, 0x76, 0x73,
0x70, 0x6d, 0x69, 0x66, 0x63, 0x60, 0x5d, 0x59, 0x56, 0x53, 0x50, 0x4d, 0x4a, 0x47, 0x44, 0x41,
0x3f, 0x3c, 0x39, 0x36, 0x34, 0x31, 0x2e, 0x2c, 0x29, 0x27, 0x25, 0x22, 0x20, 0x1e, 0x1c, 0x1a,
0x18, 0x16, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x11, 0x12, 0x14, 0x16,
0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x25, 0x27, 0x29, 0x2c, 0x2e, 0x31, 0x34, 0x36, 0x39, 0x3c,
0x3f, 0x41, 0x44, 0x47, 0x4a, 0x4d, 0x50, 0x53, 0x56, 0x59, 0x5d, 0x60, 0x63, 0x66, 0x69, 0x6d,
0x70, 0x73, 0x76, 0x7a, 0x7d, 0x80, 0x84, 0x87, 0x8a, 0x8d, 0x91, 0x94, 0x97, 0x9a, 0x9d, 0xa1,
0xa4, 0xa7, 0xaa, 0xad, 0xb0, 0xb3, 0xb6, 0xb9, 0xbc, 0xbe, 0xc1, 0xc4, 0xc6, 0xc9, 0xcc, 0xce,
0xd1, 0xd3, 0xd5, 0xd8, 0xda, 0xdc, 0xde, 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xe9, 0xeb, 0xec, 0xee,
0xef, 0xf0, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf7, 0xf8, 0xf8, 0xf9, 0xf9, 0xfa, 0xfa, 0xfa,
0xfa, 0xfa, 0xfa, 0xfa, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf0,
0xef, 0xee, 0xec, 0xeb, 0xe9, 0xe8, 0xe6, 0xe4, 0xe2, 0xe0, 0xde, 0xdc, 0xda, 0xd8, 0xd5, 0xd3,
0xd1, 0xce, 0xcc, 0xc9, 0xc6, 0xc4, 0xc1, 0xbe, 0xbc, 0xb9, 0xb6, 0xb3, 0xb0, 0xad, 0xaa, 0xa7,
0xa4, 0xa1, 0x9d, 0x9a, 0x97, 0x94, 0x91, 0x8d, 0x8a, 0x87, 0x84, 0x80, 0x7d, 0x7a, 0x76, 0x73,
0x70, 0x6d, 0x69, 0x66, 0x63, 0x60, 0x5d, 0x59, 0x56, 0x53, 0x50, 0x4d, 0x4a, 0x47, 0x44, 0x41,
0x3f, 0x3c, 0x39, 0x36, 0x34, 0x31, 0x2e, 0x2c, 0x29, 0x27, 0x25, 0x22, 0x20, 0x1e, 0x1c, 0x1a,
0x18, 0x16, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0c, 0x0b, 0x0a, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03,
0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02,
0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0x0e, 0x0f, 0x11, 0x12, 0x14, 0x16,
0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x25, 0x27, 0x29, 0x2c, 0x2e, 0x31, 0x34, 0x36, 0x39, 0x3c,
};
static const uint16_t *phase_tab[2][PHASE_CYCLE] = {
{ &space_tab[0], &space_tab[40], &space_tab[80], &space_tab[120], &space_tab[160], &space_tab[200], },
{ &mark_tab[0], &mark_tab[73], &mark_tab[147], &mark_tab[220], &mark_tab[293], &mark_tab[367], },
};

BIN
schematic.jpg 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 70 KiB

BIN
schematic.png 100644

Plik binarny nie jest wyświetlany.

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 46 KiB