mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-08-18 05:34:01 +00:00
55a15958ec
* Add P25 TX external app (UI shell)
- Register p25_tx in external.cmake and external.ld at 0xAE010000
- UI with NAC, SYSID, WACN, RFSSID, SITEID, TG, VCH fields
- 2.4 Msps TX, 155 MHz default, no baseband (m4_app_tag={0,0,0,0})
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add P25 TX baseband processor (M4)
- P25TxConfigure = 102 in message.hpp + P25TxConfigureMessage
- image_tag_p25_tx in spi_image.hpp
- set_p25tx_data() in baseband_api (copies dibits to bb_data, sends msg)
- proc_p25_tx registered in baseband CMakeLists (tag P25T)
- m4_app_tag updated to {'P','2','5','T'}
- TX wired: transmits P25 FSW test pattern (512 dibits) via M4 C4FM proc
- on_tx_progress handler stops TX when frame complete
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* p25_tx: implement correct P25 TSBK encoding from ccemu
- BCH(63,16) via generator matrix (not polynomial division)
- CRC-CCITT bit-by-bit init=0 over 80 bits
- 1/2-rate trellis encoder (4 states)
- DataInterleave per TIA-102
- Status symbol insertion (SS=0x02 every 35 dibits)
- TSBK rotation: IDEN_UP -> NET_STS -> RFSS_STS -> NET_STS
- tsbk_idx_ persists across buffer refills, resets on stop_tx
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* p25_tx: apply clang-format
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* p25_tx: fix HackRF lockup - zero output buffer when idle
When configured=false, execute() returned without writing to the
output buffer. The DMA would re-use stale IQ samples from the
previous cycle, sending garbage to the HackRF and causing it to
lock up mid-transmission.
Fix: explicitly zero the output buffer when the proc is idle.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* p25_tx: address PR review feedback and fix TX restart lockup
- Replace NumberField with SymField::Type::Hex for NAC, SYSID, WACN,
RFSSID, SITEID, TG, VCH (hex values should display as hex)
- Add voice grant TSBK (OpcodeGrpVChGrant 0x00) to rotation cycle;
rotation is now 5-step: IDEN_UP->NET_STS->RFSS_STS->GRP_V_GRANT->NET_STS
- Wire TG and VCH fields into fill_tx_buffer for voice grant encoding
- Reset txprogress_message.done=false on new P25TxConfigure in baseband
- Add #include <cstring> to baseband_api.cpp (needed for memcpy)
- Fix TX restart lockup: remove baseband::shutdown() from stop_tx() so
the M4 stays loaded between sessions; only shut down in destructor.
Previously, the stale ShutdownMessage in the queue would be picked up
by the restarted M4 on second TX, causing it to exit immediately and
leaving the HackRF stuck in TX mode.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* ifndef guard instead of pragma
173 lines
6.1 KiB
C++
173 lines
6.1 KiB
C++
/*
|
|
* 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 __SPI_IMAGE_H__
|
|
#define __SPI_IMAGE_H__
|
|
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
|
|
#include "memory_map.hpp"
|
|
|
|
extern uint32_t _textend;
|
|
|
|
namespace portapack {
|
|
namespace spi_flash {
|
|
|
|
struct image_tag_t {
|
|
constexpr image_tag_t()
|
|
: c{0, 0, 0, 0} {
|
|
}
|
|
|
|
constexpr image_tag_t(
|
|
char c0,
|
|
char c1,
|
|
char c2,
|
|
char c3)
|
|
: c{c0, c1, c2, c3} {
|
|
}
|
|
|
|
image_tag_t(const image_tag_t& other) {
|
|
c[0] = other.c[0];
|
|
c[1] = other.c[1];
|
|
c[2] = other.c[2];
|
|
c[3] = other.c[3];
|
|
}
|
|
|
|
image_tag_t& operator=(const image_tag_t& other) {
|
|
c[0] = other.c[0];
|
|
c[1] = other.c[1];
|
|
c[2] = other.c[2];
|
|
c[3] = other.c[3];
|
|
return *this;
|
|
}
|
|
|
|
bool operator==(const image_tag_t& other) const {
|
|
return (c[0] == other.c[0]) && (c[1] == other.c[1]) && (c[2] == other.c[2]) && (c[3] == other.c[3]);
|
|
}
|
|
|
|
operator bool() const {
|
|
return (c[0] != 0) || (c[1] != 0) || (c[2] != 0) || (c[3] != 0);
|
|
}
|
|
|
|
private:
|
|
char c[4];
|
|
};
|
|
|
|
constexpr image_tag_t image_tag_none{0, 0, 0, 0};
|
|
constexpr image_tag_t image_tag_audio_beep{'P', 'A', 'B', 'P'};
|
|
constexpr image_tag_t image_tag_acars{'P', 'A', 'C', 'A'};
|
|
constexpr image_tag_t image_tag_adsb_rx{'P', 'A', 'D', 'R'};
|
|
constexpr image_tag_t image_tag_afsk_rx{'P', 'A', 'F', 'R'};
|
|
constexpr image_tag_t image_tag_aprs_rx{'P', 'A', 'P', 'R'};
|
|
constexpr image_tag_t image_tag_btle_rx{'P', 'B', 'T', 'R'};
|
|
constexpr image_tag_t image_tag_btle_tx{'P', 'B', 'T', 'T'};
|
|
constexpr image_tag_t image_tag_nrf_rx{'P', 'N', 'R', 'R'};
|
|
constexpr image_tag_t image_tag_ais{'P', 'A', 'I', 'S'};
|
|
constexpr image_tag_t image_tag_am_audio{'P', 'A', 'M', 'A'};
|
|
constexpr image_tag_t image_tag_am_tv{'P', 'A', 'M', 'T'};
|
|
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_epirb_rx{'P', 'E', 'P', 'I'};
|
|
constexpr image_tag_t image_tag_epirb_tx{'P', 'E', 'P', 'T'};
|
|
constexpr image_tag_t image_tag_p25_tx{'P', '2', '5', 'T'};
|
|
constexpr image_tag_t image_tag_nfm_audio{'P', 'N', 'F', 'M'};
|
|
constexpr image_tag_t image_tag_pocsag{'P', 'P', 'O', 'C'};
|
|
constexpr image_tag_t image_tag_pocsag2{'P', 'P', 'O', '2'};
|
|
constexpr image_tag_t image_tag_flex{'P', 'F', 'L', 'X'};
|
|
constexpr image_tag_t image_tag_sonde{'P', 'S', 'O', 'N'};
|
|
constexpr image_tag_t image_tag_tpms{'P', 'T', 'P', 'M'};
|
|
constexpr image_tag_t image_tag_wfm_audio{'P', 'W', 'F', 'M'};
|
|
constexpr image_tag_t image_tag_wideband_spectrum{'P', 'S', 'P', 'E'};
|
|
constexpr image_tag_t image_tag_time_sink{'P', 'T', 'S', 'K'};
|
|
constexpr image_tag_t image_tag_test{'P', 'T', 'S', 'T'};
|
|
|
|
constexpr image_tag_t image_tag_adsb_tx{'P', 'A', 'D', 'T'};
|
|
constexpr image_tag_t image_tag_afsk{'P', 'A', 'F', 'T'};
|
|
constexpr image_tag_t image_tag_audio_tx{'P', 'A', 'T', 'X'};
|
|
constexpr image_tag_t image_tag_fsktx{'P', 'F', 'S', 'K'};
|
|
constexpr image_tag_t image_tag_fskrx{'P', 'F', 'S', 'R'};
|
|
constexpr image_tag_t image_tag_jammer{'P', 'J', 'A', 'M'};
|
|
constexpr image_tag_t image_tag_mic_tx{'P', 'M', 'T', 'X'};
|
|
constexpr image_tag_t image_tag_ook{'P', 'O', 'O', 'K'};
|
|
constexpr image_tag_t image_tag_ookstream{'P', 'O', 'S', 'K'};
|
|
constexpr image_tag_t image_tag_rds{'P', 'R', 'D', 'S'};
|
|
constexpr image_tag_t image_tag_replay{'P', 'R', 'E', 'P'};
|
|
constexpr image_tag_t image_tag_gps{'P', 'G', 'P', 'S'};
|
|
constexpr image_tag_t image_tag_siggen{'P', 'S', 'I', 'G'};
|
|
constexpr image_tag_t image_tag_spectrum_painter{'P', 'S', 'P', 'T'};
|
|
constexpr image_tag_t image_tag_sstv_tx{'P', 'S', 'T', 'X'};
|
|
constexpr image_tag_t image_tag_tones{'P', 'T', 'O', 'N'};
|
|
constexpr image_tag_t image_tag_flash_utility{'P', 'F', 'U', 'T'};
|
|
constexpr image_tag_t image_tag_usb_sd{'P', 'U', 'S', 'B'};
|
|
|
|
constexpr image_tag_t image_tag_weather{'P', 'W', 'T', 'H'};
|
|
constexpr image_tag_t image_tag_subghzd{'P', 'S', 'G', 'D'};
|
|
constexpr image_tag_t image_tag_subcar{'P', 'S', 'C', 'D'};
|
|
constexpr image_tag_t image_tag_protoview{'P', 'P', 'V', 'W'};
|
|
constexpr image_tag_t image_tag_wefaxrx{'P', 'W', 'F', 'X'};
|
|
constexpr image_tag_t image_tag_noaaapt_rx{'P', 'N', 'O', 'A'};
|
|
constexpr image_tag_t image_tag_sstv_rx{'P', 'S', 'R', 'X'};
|
|
constexpr image_tag_t image_tag_morse{'P', 'M', 'R', 'S'};
|
|
constexpr image_tag_t image_tag_morsetx{'P', 'M', 'R', 'T'};
|
|
constexpr image_tag_t image_tag_rttyrx{'P', 'R', 'T', 'R'};
|
|
constexpr image_tag_t image_tag_rttytx{'P', 'R', 'T', 'T'};
|
|
|
|
constexpr image_tag_t image_tag_noop{'P', 'N', 'O', 'P'};
|
|
|
|
constexpr image_tag_t image_tag_hackrf{'H', 'R', 'F', '1'};
|
|
|
|
struct chunk_t {
|
|
const image_tag_t tag;
|
|
const uint32_t length;
|
|
const uint32_t compressed_data_size;
|
|
const uint8_t data[];
|
|
|
|
const chunk_t* next() const {
|
|
return reinterpret_cast<const chunk_t*>(&data[length]);
|
|
}
|
|
};
|
|
|
|
struct region_t {
|
|
const size_t offset;
|
|
const size_t size;
|
|
|
|
constexpr const void* base() const {
|
|
return reinterpret_cast<void*>(portapack::memory::map::spifi_cached.base() + offset);
|
|
}
|
|
};
|
|
|
|
const region_t images{
|
|
.offset = reinterpret_cast<uint32_t>(&_textend),
|
|
.size = portapack::memory::map::spifi_cached.size() - reinterpret_cast<uint32_t>(&_textend),
|
|
};
|
|
|
|
const region_t application{
|
|
.offset = 0x00000,
|
|
.size = reinterpret_cast<uint32_t>(&_textend),
|
|
};
|
|
|
|
} /* namespace spi_flash */
|
|
} /* namespace portapack */
|
|
|
|
#endif /*__SPI_IMAGE_H__*/
|