kopia lustrzana https://github.com/amedes/pico_tnc
initial release
commit
f2fed45315
|
@ -0,0 +1,4 @@
|
|||
#
|
||||
build/
|
||||
*.un
|
||||
*~
|
|
@ -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)
|
|
@ -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.
|
|
@ -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)
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 24 KiB |
|
@ -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()
|
|
@ -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)
|
|
@ -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})
|
|
@ -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)
|
|
@ -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
|
||||
}
|
|
@ -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);
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
|
@ -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
|
||||
}
|
|
@ -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);
|
|
@ -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, ¶m.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, ¶m.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, ¶m.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, ¶m.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, ¶m.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, ¶m.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, ¶m.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(¶m, 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");
|
||||
}
|
|
@ -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);
|
|
@ -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(¶m.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
|
||||
}
|
|
@ -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);
|
|
@ -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(¶m.mycall, &packet[offset])
|
||||
|| ax25_callcmp(¶m.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
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
|
||||
bool flash_read(void *data, int len);
|
||||
bool flash_write(void *data, int len);
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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
|
@ -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;
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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
|
||||
}
|
|
@ -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);
|
|
@ -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
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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(¶m, sizeof(param));
|
||||
|
||||
// set kiss txdelay
|
||||
if (param.txdelay > 0) {
|
||||
tnc[0].kiss_txdelay = param.txdelay * 2 / 3;
|
||||
}
|
||||
}
|
|
@ -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[];
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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, ¶m.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, ¶m.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, ¶m.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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
|
@ -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
|
|
@ -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);
|
||||
|
|
@ -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], },
|
||||
};
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 70 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 46 KiB |
Ładowanie…
Reference in New Issue