diff --git a/firmware/application/CMakeLists.txt b/firmware/application/CMakeLists.txt index 4bf2ccf1..6d0c7769 100644 --- a/firmware/application/CMakeLists.txt +++ b/firmware/application/CMakeLists.txt @@ -179,8 +179,10 @@ set(CPPSRC analog_audio_app.cpp ${COMMON}/ais_baseband.cpp ${COMMON}/ais_packet.cpp + ${COMMON}/pocsag_packet.cpp ais_app.cpp tpms_app.cpp + pocsag_app.cpp ${COMMON}/tpms_packet.cpp ert_app.cpp ${COMMON}/ert_packet.cpp @@ -236,6 +238,7 @@ set(INCDIR ${CMAKE_CURRENT_BINARY_DIR} ${COMMON} ${PORTINC} ${KERNINC} ${TESTINC ${HALINC} ${PLATFORMINC} ${BOARDINC} ${FATFSINC} ${CHIBIOS}/os/various + bitmaps ) # diff --git a/firmware/application/Makefile b/firmware/application/Makefile index 971d3258..988362ee 100644 --- a/firmware/application/Makefile +++ b/firmware/application/Makefile @@ -2190,6 +2190,30 @@ __/common/png_writer.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/__/common/png_writer.cpp.s .PHONY : __/common/png_writer.cpp.s +__/common/pocsag_packet.obj: __/common/pocsag_packet.cpp.obj +.PHONY : __/common/pocsag_packet.obj + +# target to build an object file +__/common/pocsag_packet.cpp.obj: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/__/common/pocsag_packet.cpp.obj +.PHONY : __/common/pocsag_packet.cpp.obj + +__/common/pocsag_packet.i: __/common/pocsag_packet.cpp.i +.PHONY : __/common/pocsag_packet.i + +# target to preprocess a source file +__/common/pocsag_packet.cpp.i: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/__/common/pocsag_packet.cpp.i +.PHONY : __/common/pocsag_packet.cpp.i + +__/common/pocsag_packet.s: __/common/pocsag_packet.cpp.s +.PHONY : __/common/pocsag_packet.s + +# target to generate assembly for a file +__/common/pocsag_packet.cpp.s: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/__/common/pocsag_packet.cpp.s +.PHONY : __/common/pocsag_packet.cpp.s + __/common/portapack_io.obj: __/common/portapack_io.cpp.obj .PHONY : __/common/portapack_io.obj @@ -3030,6 +3054,30 @@ max5864.cpp.s: cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/max5864.cpp.s .PHONY : max5864.cpp.s +pocsag_app.obj: pocsag_app.cpp.obj +.PHONY : pocsag_app.obj + +# target to build an object file +pocsag_app.cpp.obj: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/pocsag_app.cpp.obj +.PHONY : pocsag_app.cpp.obj + +pocsag_app.i: pocsag_app.cpp.i +.PHONY : pocsag_app.i + +# target to preprocess a source file +pocsag_app.cpp.i: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/pocsag_app.cpp.i +.PHONY : pocsag_app.cpp.i + +pocsag_app.s: pocsag_app.cpp.s +.PHONY : pocsag_app.s + +# target to generate assembly for a file +pocsag_app.cpp.s: + cd /home/furrtek/portapack-hackrf && $(MAKE) -f firmware/application/CMakeFiles/application.elf.dir/build.make firmware/application/CMakeFiles/application.elf.dir/pocsag_app.cpp.s +.PHONY : pocsag_app.cpp.s + portapack.obj: portapack.cpp.obj .PHONY : portapack.obj @@ -4378,6 +4426,9 @@ help: @echo "... __/common/png_writer.obj" @echo "... __/common/png_writer.i" @echo "... __/common/png_writer.s" + @echo "... __/common/pocsag_packet.obj" + @echo "... __/common/pocsag_packet.i" + @echo "... __/common/pocsag_packet.s" @echo "... __/common/portapack_io.obj" @echo "... __/common/portapack_io.i" @echo "... __/common/portapack_io.s" @@ -4483,6 +4534,9 @@ help: @echo "... max5864.obj" @echo "... max5864.i" @echo "... max5864.s" + @echo "... pocsag_app.obj" + @echo "... pocsag_app.i" + @echo "... pocsag_app.s" @echo "... portapack.obj" @echo "... portapack.i" @echo "... portapack.s" diff --git a/firmware/application/baseband_api.cpp b/firmware/application/baseband_api.cpp index 8732eda5..62dfbcc1 100644 --- a/firmware/application/baseband_api.cpp +++ b/firmware/application/baseband_api.cpp @@ -133,6 +133,13 @@ void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, send_message(&message); } +void set_pocsag() { + const POCSAGConfigureMessage message { + 1200 + }; + send_message(&message); +} + static bool baseband_image_running = false; void run_image(const portapack::spi_flash::image_tag_t image_tag) { diff --git a/firmware/application/baseband_api.hpp b/firmware/application/baseband_api.hpp index 9b175f6f..01fea395 100644 --- a/firmware/application/baseband_api.hpp +++ b/firmware/application/baseband_api.hpp @@ -60,6 +60,7 @@ void set_afsk_data(const uint32_t afsk_samples_per_bit, const uint32_t afsk_phas const uint8_t afsk_repeat, const uint32_t afsk_bw, const bool afsk_alt_format); void set_ook_data(const uint32_t stream_length, const uint32_t samples_per_bit, const uint8_t repeat, const uint32_t pause_symbols); +void set_pocsag(); void run_image(const portapack::spi_flash::image_tag_t image_tag); void shutdown(); diff --git a/firmware/application/bitmap.hpp b/firmware/application/bitmap.hpp index 47ee91d6..6842fb92 100644 --- a/firmware/application/bitmap.hpp +++ b/firmware/application/bitmap.hpp @@ -97,22 +97,22 @@ static constexpr Bitmap bitmap_keyboard { }; static constexpr uint8_t bitmap_unistroke_data[] = { + 0x33, 0xC0, + 0x33, 0x00, + 0xB3, 0xCD, + 0xB3, 0xDF, + 0xB3, 0xD9, + 0xB3, 0xD9, + 0x9E, 0xD9, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x00, - 0x22, 0x00, - 0x22, 0x00, - 0x22, 0x00, - 0x22, 0x00, - 0x22, 0x00, - 0xA2, 0x73, - 0xA2, 0x24, - 0xA2, 0x24, - 0xA2, 0x24, - 0xA2, 0x24, - 0x9C, 0x74, - 0x00, 0x00, - 0x00, 0x00, + 0x00, 0x1C, + 0x06, 0x3E, + 0x06, 0x67, + 0xCE, 0x43, + 0xFC, 0x01, + 0x78, 0x40, + 0x00, 0x00 }; static constexpr Bitmap bitmap_unistroke { diff --git a/firmware/application/bulb_ignore_bmp.hpp b/firmware/application/bitmaps/bmp_bulb_ignore.hpp similarity index 100% rename from firmware/application/bulb_ignore_bmp.hpp rename to firmware/application/bitmaps/bmp_bulb_ignore.hpp diff --git a/firmware/application/bulb_off_bmp.hpp b/firmware/application/bitmaps/bmp_bulb_off.hpp similarity index 100% rename from firmware/application/bulb_off_bmp.hpp rename to firmware/application/bitmaps/bmp_bulb_off.hpp diff --git a/firmware/application/bulb_on_bmp.hpp b/firmware/application/bitmaps/bmp_bulb_on.hpp similarity index 100% rename from firmware/application/bulb_on_bmp.hpp rename to firmware/application/bitmaps/bmp_bulb_on.hpp diff --git a/firmware/application/fox_bmp.hpp b/firmware/application/bitmaps/bmp_fox.hpp similarity index 100% rename from firmware/application/fox_bmp.hpp rename to firmware/application/bitmaps/bmp_fox.hpp diff --git a/firmware/application/bitmaps/bmp_modal_warning.hpp b/firmware/application/bitmaps/bmp_modal_warning.hpp new file mode 100644 index 00000000..7c49d21e --- /dev/null +++ b/firmware/application/bitmaps/bmp_modal_warning.hpp @@ -0,0 +1,73 @@ +unsigned char modal_warning_bmp[] = { + 0x42, 0x4d, 0xfa, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, + 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa8, 0x02, + 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x07, 0x00, + 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xff, 0x00, 0x00, 0x5a, + 0xff, 0x00, 0x78, 0x78, 0x78, 0x00, 0x00, 0x7c, 0xff, 0x00, 0x00, 0xa9, + 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x02, 0x03, 0x24, 0x66, 0x02, 0x30, + 0x00, 0x00, 0x02, 0x36, 0x24, 0x66, 0x02, 0x63, 0x00, 0x00, 0x02, 0x66, + 0x02, 0x63, 0x20, 0x00, 0x02, 0x36, 0x02, 0x66, 0x00, 0x00, 0x02, 0x36, + 0x02, 0x60, 0x20, 0x00, 0x02, 0x06, 0x02, 0x63, 0x00, 0x00, 0x02, 0x06, + 0x02, 0x60, 0x0c, 0x00, 0x00, 0x08, 0x03, 0x66, 0x66, 0x30, 0x0c, 0x00, + 0x02, 0x06, 0x02, 0x60, 0x00, 0x00, 0x02, 0x03, 0x02, 0x66, 0x0c, 0x00, + 0x00, 0x08, 0x06, 0x11, 0x11, 0x60, 0x0c, 0x00, 0x02, 0x66, 0x02, 0x30, + 0x00, 0x00, 0x02, 0x00, 0x02, 0x66, 0x0c, 0x00, 0x00, 0x08, 0x06, 0x21, + 0x21, 0x60, 0x0c, 0x00, 0x02, 0x66, 0x02, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x36, 0x60, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x06, 0x42, 0x42, 0x60, + 0x0a, 0x00, 0x00, 0x06, 0x06, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x06, 0x60, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x06, 0x54, 0x45, 0x60, + 0x0a, 0x00, 0x00, 0x06, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x03, 0x66, 0x00, 0x0a, 0x00, 0x00, 0x08, 0x03, 0x66, 0x66, 0x30, + 0x0a, 0x00, 0x00, 0x06, 0x66, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x66, 0x00, 0x1c, 0x00, 0x00, 0x06, 0x66, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x36, 0x60, 0x18, 0x00, 0x00, 0x08, + 0x06, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x60, + 0x0a, 0x00, 0x02, 0x36, 0x02, 0x63, 0x0a, 0x00, 0x00, 0x08, 0x06, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x66, 0x08, 0x00, + 0x00, 0x08, 0x03, 0x61, 0x16, 0x30, 0x08, 0x00, 0x00, 0x08, 0x66, 0x30, + 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x66, 0x08, 0x00, 0x00, 0x08, + 0x06, 0x11, 0x11, 0x60, 0x08, 0x00, 0x02, 0x66, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x02, 0x36, 0x02, 0x60, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11, + 0x11, 0x60, 0x06, 0x00, 0x02, 0x06, 0x02, 0x63, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x02, 0x06, 0x02, 0x60, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11, + 0x11, 0x60, 0x06, 0x00, 0x02, 0x06, 0x02, 0x60, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x02, 0x03, 0x02, 0x66, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11, + 0x11, 0x60, 0x06, 0x00, 0x02, 0x66, 0x02, 0x30, 0x06, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x02, 0x66, 0x06, 0x00, 0x00, 0x08, 0x06, 0x11, 0x11, 0x60, + 0x06, 0x00, 0x02, 0x66, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, + 0x36, 0x60, 0x00, 0x00, 0x06, 0x11, 0x11, 0x60, 0x00, 0x00, 0x06, 0x63, + 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x06, 0x60, 0x00, 0x00, + 0x06, 0x21, 0x21, 0x60, 0x00, 0x00, 0x06, 0x60, 0x08, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x18, 0x03, 0x66, 0x00, 0x00, 0x06, 0x12, 0x12, 0x60, + 0x00, 0x00, 0x66, 0x30, 0x08, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x14, + 0x66, 0x00, 0x00, 0x06, 0x21, 0x21, 0x60, 0x00, 0x00, 0x66, 0x0a, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x14, 0x36, 0x60, 0x00, 0x06, 0x22, 0x22, + 0x60, 0x00, 0x06, 0x63, 0x0a, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x14, + 0x06, 0x60, 0x00, 0x06, 0x24, 0x24, 0x60, 0x00, 0x06, 0x60, 0x0a, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x14, 0x03, 0x66, 0x00, 0x06, 0x42, 0x42, + 0x60, 0x00, 0x66, 0x30, 0x0a, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x10, + 0x66, 0x00, 0x06, 0x54, 0x45, 0x60, 0x00, 0x66, 0x0c, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x10, 0x36, 0x60, 0x03, 0x66, 0x66, 0x30, 0x06, 0x63, + 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x06, 0x02, 0x60, 0x08, 0x00, + 0x02, 0x06, 0x02, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x02, 0x03, + 0x02, 0x66, 0x08, 0x00, 0x02, 0x66, 0x02, 0x30, 0x0c, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x02, 0x66, 0x08, 0x00, 0x02, 0x66, 0x0e, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x0c, 0x36, 0x60, 0x00, 0x00, 0x06, 0x63, 0x0e, 0x00, + 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0c, 0x06, 0x60, 0x00, 0x00, 0x06, 0x60, + 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x0c, 0x03, 0x66, 0x00, 0x00, + 0x66, 0x30, 0x0e, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x66, 0x00, + 0x00, 0x66, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x36, 0x60, + 0x06, 0x63, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x06, 0x60, + 0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x03, 0x66, + 0x66, 0x30, 0x10, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x66, 0x02, 0x66, + 0x12, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x36, 0x02, 0x63, 0x12, 0x00, + 0x00, 0x01 +}; +unsigned int modal_warning_bmp_len = 830; diff --git a/firmware/application/splash.hpp b/firmware/application/bitmaps/bmp_splash.hpp similarity index 100% rename from firmware/application/splash.hpp rename to firmware/application/bitmaps/bmp_splash.hpp diff --git a/firmware/bitmaps/bulb_ignore.bmp b/firmware/application/bitmaps/bulb_ignore.bmp similarity index 100% rename from firmware/bitmaps/bulb_ignore.bmp rename to firmware/application/bitmaps/bulb_ignore.bmp diff --git a/firmware/bitmaps/bulb_off.bmp b/firmware/application/bitmaps/bulb_off.bmp similarity index 100% rename from firmware/bitmaps/bulb_off.bmp rename to firmware/application/bitmaps/bulb_off.bmp diff --git a/firmware/bitmaps/bulb_on.bmp b/firmware/application/bitmaps/bulb_on.bmp similarity index 100% rename from firmware/bitmaps/bulb_on.bmp rename to firmware/application/bitmaps/bulb_on.bmp diff --git a/firmware/bitmaps/fox.bmp b/firmware/application/bitmaps/fox.bmp similarity index 100% rename from firmware/bitmaps/fox.bmp rename to firmware/application/bitmaps/fox.bmp diff --git a/firmware/application/bitmaps/modal_warning.bmp b/firmware/application/bitmaps/modal_warning.bmp new file mode 100644 index 00000000..d440f73c Binary files /dev/null and b/firmware/application/bitmaps/modal_warning.bmp differ diff --git a/firmware/bitmaps/splash.bmp b/firmware/application/bitmaps/splash.bmp similarity index 100% rename from firmware/bitmaps/splash.bmp rename to firmware/application/bitmaps/splash.bmp diff --git a/firmware/application/pocsag_app.cpp b/firmware/application/pocsag_app.cpp new file mode 100644 index 00000000..940b89cd --- /dev/null +++ b/firmware/application/pocsag_app.cpp @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "pocsag_app.hpp" + +#include "baseband_api.hpp" + +#include "portapack.hpp" +using namespace portapack; + +#include "string_format.hpp" + +#include "utility.hpp" + +#define POCSAG_IDLE 0x7A89C197 + +namespace pocsag { + +namespace format { + +static std::string signal_rate_str(SignalRate signal_rate) { + switch(signal_rate) { + case SignalRate::FSK512: return "FSK 512 "; + case SignalRate::FSK1200: return "FSK 1200"; + case SignalRate::FSK2400: return "FSK 2400"; + default: return "- - - - "; + } +} + +} /* namespace format */ + +} /* namespace pocsag */ + +void POCSAGLogger::on_packet(const pocsag::POCSAGPacket& packet) { + std::string entry = pocsag::format::signal_rate_str(packet.signal_rate()) + " "; + for (size_t c = 0; c < 16; c++) + entry += to_string_hex(packet[c], 8) + " "; + + log_file.write_entry(packet.timestamp(), entry); +} + +namespace ui { + +POCSAGAppView::POCSAGAppView(NavigationView& nav) { + baseband::run_image(portapack::spi_flash::image_tag_pocsag); + + add_children({ { + &rssi, + &channel, + &options_band, + &field_rf_amp, + &field_lna, + &field_vga, + //&text_debug, + &console + } }); + + radio::enable({ + tuning_frequency(), + sampling_rate, + baseband_bandwidth, + rf::Direction::Receive, + receiver_model.rf_amp(), + static_cast(receiver_model.lna()), + static_cast(receiver_model.vga()), + 1, + }); + + options_band.on_change = [this](size_t, OptionsField::value_t v) { + this->on_band_changed(v); + }; + options_band.set_by_value(target_frequency()); + + logger = std::make_unique(); + if( logger ) { + logger->append("pocsag.txt"); + } + + baseband::set_pocsag(); +} + +POCSAGAppView::~POCSAGAppView() { + radio::disable(); + baseband::shutdown(); +} + +void POCSAGAppView::focus() { + options_band.focus(); +} + +void POCSAGAppView::set_parent_rect(const Rect new_parent_rect) { + View::set_parent_rect(new_parent_rect); +} + +void POCSAGAppView::on_packet(const POCSAGPacketMessage * message) { + bool eom = false; + uint32_t codeword; + + if( logger ) { + logger->on_packet(message->packet); + } + + for (size_t c = 0; c < 16; c++) { + codeword = message->packet[c]; + + if (codeword & 0x80000000) { + // Message + console.writeln("Message !"); + + } else { + // Address + if (codeword == POCSAG_IDLE) { + eom = true; + } else { + function = (codeword >> 11) & 3; + address = ((codeword >> 10) & 0x1FFFF8) | ((codeword >> 1) & 7); + } + } + } + + if (eom) + console.writeln("Address:" + to_string_hex(address, 6) + " Function:" + to_string_dec_uint(function)); + //console.writeln("EOM"); + //console.writeln(to_string_hex(message->packet[0], 8) + "/"+ to_string_hex(message->packet[1], 8)); + + if (eom) + batch_cnt = 0; + else + batch_cnt++; +} + +void POCSAGAppView::on_band_changed(const uint32_t new_band_frequency) { + set_target_frequency(new_band_frequency); +} + +void POCSAGAppView::set_target_frequency(const uint32_t new_value) { + target_frequency_ = new_value; + radio::set_tuning_frequency(tuning_frequency()); +} + +uint32_t POCSAGAppView::target_frequency() const { + return target_frequency_; +} + +uint32_t POCSAGAppView::tuning_frequency() const { + return target_frequency() - (sampling_rate / 4); +} + +} /* namespace ui */ diff --git a/firmware/application/pocsag_app.hpp b/firmware/application/pocsag_app.hpp new file mode 100644 index 00000000..dc2e399a --- /dev/null +++ b/firmware/application/pocsag_app.hpp @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __POCSAG_APP_H__ +#define __POCSAG_APP_H__ + +#include "ui_widget.hpp" +#include "ui_navigation.hpp" +#include "ui_receiver.hpp" +#include "ui_rssi.hpp" +#include "ui_channel.hpp" + +#include "event_m0.hpp" + +#include "log_file.hpp" + +#include "pocsag_packet.hpp" + +class POCSAGLogger { +public: + Optional append(const std::string& filename) { + return log_file.append(filename); + } + + void on_packet(const pocsag::POCSAGPacket& packet); + +private: + LogFile log_file; +}; + +namespace ui { + +class POCSAGAppView : public View { +public: + POCSAGAppView(NavigationView& nav); + ~POCSAGAppView(); + + void set_parent_rect(const Rect new_parent_rect) override; + + void paint(Painter&) override { }; + + void focus() override; + + std::string title() const override { return "POCSAG RX"; }; + +private: + static constexpr uint32_t initial_target_frequency = 466175000; + static constexpr uint32_t sampling_rate = 1536000; + static constexpr uint32_t baseband_bandwidth = 1750000; + + uint32_t batch_cnt = 0; + uint32_t address, function; + + MessageHandlerRegistration message_handler_packet { + Message::ID::POCSAGPacket, + [this](Message* const p) { + const auto message = static_cast(p); + this->on_packet(message); + } + }; + + static constexpr ui::Dim header_height = 1 * 16; + + RSSI rssi { + { 21 * 8, 0, 6 * 8, 4 }, + }; + + Channel channel { + { 21 * 8, 5, 6 * 8, 4 }, + }; + + OptionsField options_band { + { 0 * 8, 0 * 16 }, + 7, + { + { "FR .025", 466025000 }, + { "FR .050", 466050000 }, + { "FR .075", 466075000 }, + { "FR .175", 466175000 }, + { "FR .206", 466206250 }, + { "FR .231", 466231250 } + } + }; + + Text text_debug { + { 0, 40, 240, 16 }, + "Debug..." + }; + + Console console { + { 0, 32, 240, 272 } + }; + + RFAmpField field_rf_amp { + { 13 * 8, 0 * 16 } + }; + + LNAGainField field_lna { + { 15 * 8, 0 * 16 } + }; + + VGAGainField field_vga { + { 18 * 8, 0 * 16 } + }; + + std::unique_ptr logger; + + uint32_t target_frequency_ = initial_target_frequency; + + void on_packet(const POCSAGPacketMessage * message); + void on_show_list(); + + void on_band_changed(const uint32_t new_band_frequency); + + uint32_t target_frequency() const; + void set_target_frequency(const uint32_t new_value); + + uint32_t tuning_frequency() const; +}; + +} /* namespace ui */ + +#endif/*__POCSAG_APP_H__*/ diff --git a/firmware/application/string_format.cpp b/firmware/application/string_format.cpp index 5e151297..156faaa8 100644 --- a/firmware/application/string_format.cpp +++ b/firmware/application/string_format.cpp @@ -99,7 +99,7 @@ std::string to_string_dec_int( static void to_string_hex_internal(char* p, const uint32_t n, const int32_t l) { const uint32_t d = n & 0xf; - p[l] = (d > 9) ? (d + 87) : (d + 48); + p[l] = (d > 9) ? (d + 55) : (d + 48); if( l > 0 ) { to_string_hex_internal(p, n >> 4, l - 1); } diff --git a/firmware/application/ui_alphanum.cpp b/firmware/application/ui_alphanum.cpp index c4155ff9..6e49ce7d 100644 --- a/firmware/application/ui_alphanum.cpp +++ b/firmware/application/ui_alphanum.cpp @@ -116,7 +116,7 @@ AlphanumView::AlphanumView( add_child(&button_done); button_done.on_select = [this, &nav, txt, max_len](Button&) { memcpy(txt, txtinput, max_len + 1); - on_changed(this->value()); + if (on_changed) on_changed(this->value()); nav.pop(); }; diff --git a/firmware/application/ui_navigation.cpp b/firmware/application/ui_navigation.cpp index aba9e24b..2fc35cff 100644 --- a/firmware/application/ui_navigation.cpp +++ b/firmware/application/ui_navigation.cpp @@ -28,7 +28,8 @@ #include "portapack.hpp" #include "event_m0.hpp" #include "portapack_persistent_memory.hpp" -#include "splash.hpp" +#include "bmp_splash.hpp" +#include "bmp_modal_warning.hpp" #include "ui_about.hpp" #include "ui_setup.hpp" @@ -52,6 +53,7 @@ #include "ais_app.hpp" #include "ert_app.hpp" #include "tpms_app.hpp" +#include "pocsag_app.hpp" #include "capture_app.hpp" #include "core_control.hpp" @@ -184,7 +186,7 @@ void NavigationView::display_modal( ) { /* If a modal view is already visible, don't display another */ if( !modal_view ) { - modal_view = push(title, message); + modal_view = push(title, message, false); } } @@ -228,9 +230,10 @@ TranspondersMenuView::TranspondersMenuView(NavigationView& nav) { /* ReceiverMenuView ******************************************************/ ReceiverMenuView::ReceiverMenuView(NavigationView& nav) { - add_items<2>({ { + add_items<3>({ { { "Audio", ui::Color::white(), [&nav](){ nav.push(); } }, { "Transponders", ui::Color::white(), [&nav](){ nav.push(); } }, + { "POCSAG", ui::Color::cyan(), [&nav](){ nav.push(); } }, } }); on_left = [&nav](){ nav.pop(); }; } @@ -437,17 +440,37 @@ void NotImplementedView::focus() { ModalMessageView::ModalMessageView( NavigationView& nav, const std::string& title, - const std::string& message -) : title_ { title } + const std::string& message, + bool yesno +) : title_ { title }, + yesno_ { yesno } { - button_done.on_select = [&nav](Button&){ - nav.pop(); - }; - add_children({ { - &text_message, - &button_done, - } }); + if (!yesno) { + button_done.on_select = [&nav](Button&){ + nav.pop(); + }; + + add_children({ { + &text_message, + &button_done + } }); + } else { + button_yes.on_select = [this,&nav](Button&){ + if (on_choice) on_choice(true); + nav.pop(); + }; + button_no.on_select = [this,&nav](Button&){ + if (on_choice) on_choice(false); + nav.pop(); + }; + + add_children({ { + &text_message, + &button_yes, + &button_no + } }); + } text_message.set(message); @@ -458,8 +481,17 @@ ModalMessageView::ModalMessageView( }); } +void ModalMessageView::paint(Painter& painter) { + (void)painter; + portapack::display.drawBMP({64, 64}, modal_warning_bmp, false); +} + void ModalMessageView::focus() { - button_done.focus(); + if (!yesno_) { + button_done.focus(); + } else { + button_yes.focus(); + } } } /* namespace ui */ diff --git a/firmware/application/ui_navigation.hpp b/firmware/application/ui_navigation.hpp index 40c3e060..9ec130a1 100644 --- a/firmware/application/ui_navigation.hpp +++ b/firmware/application/ui_navigation.hpp @@ -264,15 +264,20 @@ public: ModalMessageView( NavigationView& nav, const std::string& title, - const std::string& message + const std::string& message, + bool yesno ); + void paint(Painter& painter) override; void focus() override; std::string title() const override { return title_; }; + + std::function on_choice; private: const std::string title_; + const bool yesno_; Text text_message { }; @@ -280,6 +285,15 @@ private: { 10 * 8, 13 * 16, 10 * 8, 24 }, "OK", }; + + Button button_yes { + { 40, 13 * 16, 64, 24 }, + "YES", + }; + Button button_no { + { 152, 13 * 16, 64, 24 }, + "NO", + }; }; } /* namespace ui */ diff --git a/firmware/application/ui_xylos.cpp b/firmware/application/ui_xylos.cpp index d5e33cfd..40a844a5 100644 --- a/firmware/application/ui_xylos.cpp +++ b/firmware/application/ui_xylos.cpp @@ -415,14 +415,19 @@ XylosView::XylosView(NavigationView& nav) { };*/ // Single transmit - button_transmit.on_select = [this](Button&) { + button_transmit.on_select = [this,&nav](Button&) { if (tx_mode == IDLE) { - // audio::headphone::set_volume(volume_t::decibel(90 - 99) + audio::headphone::volume_range().max); - tx_mode = SINGLE; - button_transmit.set_style(&style_cancel); - button_transmit.set_text("Wait"); - generate_message(); - start_tx(); + /*auto modal_view = nav.push("TX", "TX ?", true); + modal_view->on_choice = [this](bool choice) { + if (choice) {*/ + // audio::headphone::set_volume(volume_t::decibel(90 - 99) + audio::headphone::volume_range().max); + tx_mode = SINGLE; + button_transmit.set_style(&style_cancel); + button_transmit.set_text("Wait"); + generate_message(); + start_tx(); + //} + //}; } }; } diff --git a/firmware/application/ui_xylos.hpp b/firmware/application/ui_xylos.hpp index 9b97a0e5..5299b870 100644 --- a/firmware/application/ui_xylos.hpp +++ b/firmware/application/ui_xylos.hpp @@ -25,9 +25,9 @@ #include "ui_navigation.hpp" #include "ui_font_fixed_8x16.hpp" -#include "bulb_on_bmp.hpp" -#include "bulb_off_bmp.hpp" -#include "bulb_ignore_bmp.hpp" +#include "bmp_bulb_on.hpp" +#include "bmp_bulb_off.hpp" +#include "bmp_bulb_ignore.hpp" #include "message.hpp" //#include "volume.hpp" diff --git a/firmware/baseband/CMakeLists.txt b/firmware/baseband/CMakeLists.txt index 5b9dc8ef..548a2831 100644 --- a/firmware/baseband/CMakeLists.txt +++ b/firmware/baseband/CMakeLists.txt @@ -298,6 +298,13 @@ set(MODE_CPPSRC ) DeclareTargets(PERT ert) +### POCSAG RX + +set(MODE_CPPSRC + proc_pocsag.cpp +) +DeclareTargets(PPOC pocsag) + ### NFM Audio set(MODE_CPPSRC diff --git a/firmware/baseband/proc_pocsag.cpp b/firmware/baseband/proc_pocsag.cpp new file mode 100644 index 00000000..b4fa467c --- /dev/null +++ b/firmware/baseband/proc_pocsag.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu) + * Copyright (C) 2012-2014 Elias Oenal (multimon-ng@eliasoenal.com) + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "proc_pocsag.hpp" + +#include "event_m4.hpp" + +#include +#include + +#define FREQ_SAMP 24000 +#define BAUD 1200 +#define SPHASEINC (0x10000u * BAUD / FREQ_SAMP) + +#define POCSAG_SYNC 0x7CD215D8 +#define POCSAG_IDLE 0x7A89C197 + +void POCSAGProcessor::execute(const buffer_c8_t& buffer) { + /* 1.536MHz, 2048 samples */ + + if( !configured ) return; + + const auto decim_0_out = decim_0.execute(buffer, dst_buffer); + const auto decim_1_out = decim_1.execute(decim_0_out, dst_buffer); + + auto audio = demod.execute(decim_1_out, audio_buffer); + + for (c = 0; c < 32; c++) { + + // Bit = sign + const int32_t sample_int = audio.p[c] * 32768.0f; + const int32_t audio_sample = __SSAT(sample_int, 16); + dcd_shreg <<= 1; + dcd_shreg |= (audio_sample < 0); + + // Detect transitions to adjust clock + if ((dcd_shreg ^ (dcd_shreg >> 1)) & 1) { + if (sphase < (0x8000u-(SPHASEINC/2))) + sphase += SPHASEINC/8; + else + sphase -= SPHASEINC/8; + } + + sphase += SPHASEINC; + + if (sphase >= 0x10000u) { + sphase &= 0xffffu; + + rx_data <<= 1; + rx_data |= (dcd_shreg & 1); + + switch(rx_state) { + + case WAITING: + if (rx_data == 0xAAAAAAAA) { + rx_state = PREAMBLE; + sync_timeout = 0; + } + break; + + case PREAMBLE: + if (sync_timeout < 600) { + sync_timeout++; + + //pocsag_brute_repair(&s->l2.pocsag, &rx_data); + + if (rx_data == POCSAG_SYNC) { + packet.clear(); + rx_state = SYNC; + frame_counter = 0; + rx_bit = 0; + } else if (rx_data == POCSAG_IDLE) { + rx_state = WAITING; + } + + } else { + rx_state = WAITING; // Abort + } + break; + + case SYNC: + rx_bit++; + if (rx_bit >= 32) { + rx_bit = 0; + + //pocsag_brute_repair(&s->l2.pocsag, &rx_data); + + packet.set(frame_counter, rx_data); + + if (rx_data == POCSAG_IDLE) { + rx_state = WAITING; + + packet.set_timestamp(Timestamp::now()); + //packet.rate = pocsag::SignalRate::FSK1200; + + const POCSAGPacketMessage message(packet); + shared_memory.application_queue.push(message); + + } else { + if (frame_counter < 15) + frame_counter++; + else + rx_state = WAITING; + } + } + break; + + default: + break; + } + } + } +} + +void POCSAGProcessor::on_message(const Message* const message) { + if (message->id == Message::ID::POCSAGConfigure) + configure(*reinterpret_cast(message)); +} + +void POCSAGProcessor::configure(const POCSAGConfigureMessage& message) { + (void)message; + + constexpr size_t decim_0_input_fs = baseband_fs; + constexpr size_t decim_0_output_fs = decim_0_input_fs / decim_0.decimation_factor; + + constexpr size_t decim_1_input_fs = decim_0_output_fs; + constexpr size_t decim_1_output_fs = decim_1_input_fs / decim_1.decimation_factor; + + const size_t demod_input_fs = decim_1_output_fs; + + decim_0.configure(taps_11k0_decim_0.taps, 33554432); + decim_1.configure(taps_11k0_decim_1.taps, 131072); + demod.configure(demod_input_fs, 4500); + + rx_state = WAITING; + configured = true; +} + +int main() { + EventDispatcher event_dispatcher { std::make_unique() }; + event_dispatcher.run(); + return 0; +} diff --git a/firmware/baseband/proc_pocsag.hpp b/firmware/baseband/proc_pocsag.hpp new file mode 100644 index 00000000..76c5a860 --- /dev/null +++ b/firmware/baseband/proc_pocsag.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PROC_POCSAG_H__ +#define __PROC_POCSAG_H__ + +#include "baseband_processor.hpp" +#include "baseband_thread.hpp" +#include "rssi_thread.hpp" + +#include "dsp_iir.hpp" +#include "dsp_decimate.hpp" +#include "dsp_demodulate.hpp" + +#include "pocsag_packet.hpp" + +#include "message.hpp" +#include "portapack_shared_memory.hpp" + +#include + +class POCSAGProcessor : public BasebandProcessor { +public: + void execute(const buffer_c8_t& buffer) override; + + void on_message(const Message* const message) override; + +private: + enum rx_states { + WAITING = 0, + PREAMBLE = 32, + SYNC = 64, + LOSING_SYNC = 65, + LOST_SYNC = 66, + ADDRESS = 67, + MESSAGE = 68, + END_OF_MESSAGE = 69 + }; + + static constexpr size_t baseband_fs = 1536000; + + BasebandThread baseband_thread { baseband_fs, this, NORMALPRIO + 20, baseband::Direction::Receive }; + RSSIThread rssi_thread { NORMALPRIO + 10 }; + + std::array dst; + const buffer_c16_t dst_buffer { + dst.data(), + dst.size() + }; + std::array audio; + const buffer_f32_t audio_buffer { + audio.data(), + audio.size() + }; + + dsp::decimate::FIRC8xR16x24FS4Decim8 decim_0; + dsp::decimate::FIRC16xR16x32Decim8 decim_1; + + dsp::demodulate::FM demod; + + uint32_t sync_timeout; + + uint32_t dcd_shreg; + uint32_t sphase; + uint32_t rx_data; + uint32_t rx_bit; + bool configured = false; + rx_states rx_state; + + size_t c, frame_counter; + + pocsag::POCSAGPacket packet; + + void configure(const POCSAGConfigureMessage& message); + +}; + +#endif/*__PROC_POCSAG_H__*/ diff --git a/firmware/common/dsp_iir_config.hpp b/firmware/common/dsp_iir_config.hpp index 50aca1d5..657d0197 100644 --- a/firmware/common/dsp_iir_config.hpp +++ b/firmware/common/dsp_iir_config.hpp @@ -40,6 +40,7 @@ constexpr iir_biquad_config_t audio_48k_hpf_300hz_config { constexpr iir_biquad_config_t audio_24k_hpf_300hz_config { { 0.94597686f, -1.89195371f, 0.94597686f }, { 1.00000000f, -1.88903308f, 0.89487434f } + }; // scipy.signal.butter(2, 300 / 8000.0, 'highpass', analog=False) diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 6cbdba66..71a6f31e 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -32,6 +32,7 @@ #include "baseband_packet.hpp" #include "ert_packet.hpp" #include "tpms_packet.hpp" +#include "pocsag_packet.hpp" #include "dsp_fir_taps.hpp" #include "dsp_iir.hpp" #include "fifo.hpp" @@ -73,9 +74,12 @@ public: OOKConfigure = 25, RDSConfigure = 26, AudioTXConfig = 27, + POCSAGConfigure = 28, - FIFOSignal = 28, - FIFOData = 29, + POCSAGPacket = 30, + + FIFOSignal = 31, + FIFOData = 32, MAX }; @@ -270,6 +274,18 @@ public: baseband::Packet packet; }; +class POCSAGPacketMessage : public Message { +public: + constexpr POCSAGPacketMessage( + const pocsag::POCSAGPacket& packet + ) : Message { ID::POCSAGPacket }, + packet { packet } + { + } + + pocsag::POCSAGPacket packet; +}; + class ShutdownMessage : public Message { public: constexpr ShutdownMessage( @@ -602,6 +618,18 @@ public: const uint32_t pause_symbols; }; +class POCSAGConfigureMessage : public Message { +public: + constexpr POCSAGConfigureMessage( + const uint32_t rate + ) : Message { ID::POCSAGConfigure }, + rate(rate) + { + } + + const uint32_t rate; +}; + // TODO: use streaming buffer instead class FIFOSignalMessage : public Message { public: diff --git a/firmware/common/pocsag_packet.cpp b/firmware/common/pocsag_packet.cpp new file mode 100644 index 00000000..88bbc997 --- /dev/null +++ b/firmware/common/pocsag_packet.cpp @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "pocsag_packet.hpp" + +namespace pocsag { + +} /* namespace pocsag */ diff --git a/firmware/common/pocsag_packet.hpp b/firmware/common/pocsag_packet.hpp new file mode 100644 index 00000000..f06ac960 --- /dev/null +++ b/firmware/common/pocsag_packet.hpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * Copyright (C) 2016 Furrtek + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __POCSAG_PACKET_H__ +#define __POCSAG_PACKET_H__ + +#include +#include + +#include "optional.hpp" + +#include "baseband.hpp" + +namespace pocsag { + +enum SignalRate : uint32_t { + FSK512 = 1, + FSK1200 = 2, + FSK2400 = 3, + DEBUG = 4 +}; + +class POCSAGPacket { +public: + void set_timestamp(const Timestamp& value) { + timestamp_ = value; + } + + Timestamp timestamp() const { + return timestamp_; + } + + void set(const size_t index, const uint32_t data) { + if (index < 16) + codewords[index] = data; + } + + uint32_t operator[](const size_t index) const { + return (index < 16) ? codewords[index] : 0; + } + + SignalRate signal_rate() const { + return FSK1200; + } + + void clear() { + for (size_t c = 0; c < 16; c++) + codewords[c] = 0; + } + +private: + //SignalRate rate = FSK1200; + uint32_t codewords[16]; + Timestamp timestamp_ { }; +}; + +} /* namespace pocsag */ + +#endif/*__POCSAG_PACKET_H__*/ diff --git a/firmware/common/spi_image.hpp b/firmware/common/spi_image.hpp index fa1cfa4f..90ccd452 100644 --- a/firmware/common/spi_image.hpp +++ b/firmware/common/spi_image.hpp @@ -68,6 +68,7 @@ constexpr image_tag_t image_tag_capture { 'P', 'C', 'A', 'P' }; constexpr image_tag_t image_tag_ert { 'P', 'E', 'R', 'T' }; constexpr image_tag_t image_tag_nfm_audio { 'P', 'N', 'F', 'M' }; constexpr image_tag_t image_tag_tpms { 'P', 'T', 'P', 'M' }; +constexpr image_tag_t image_tag_pocsag { 'P', 'P', 'O', 'C' }; constexpr image_tag_t image_tag_wfm_audio { 'P', 'W', 'F', 'M' }; constexpr image_tag_t image_tag_wideband_spectrum { 'P', 'S', 'P', 'E' }; diff --git a/firmware/portapack-h1-firmware.bin b/firmware/portapack-h1-firmware.bin index 548ba57c..d257526b 100644 Binary files a/firmware/portapack-h1-firmware.bin and b/firmware/portapack-h1-firmware.bin differ