Compare commits

...

7 Commits

Author SHA1 Message Date
jLynx 53bbf74f4d V1.9.0 (#1660)
* Update version.txt

* Update past_version.txt
2023-12-22 07:35:54 +13:00
Mark Thompson 19a66fac20 Enable Sample Rate to be spec'd in .ini file for Weather & SubGhzDecoder apps (#1659) 2023-12-21 19:33:06 +01:00
Totoo 36e1b9a36e Portapack USB screen tx (#1653)
* implemented 2 screen read functions, and haxfixed windows usb bug
* Support up to 64 byte per packet for faster tx
* Added filesize command
2023-12-19 22:25:22 +01:00
Netro 1ca9288bbe initial USB serial thread integrated to BLE RX (#1651) 2023-12-19 22:20:13 +01:00
Mark Thompson 4ca2d1e352 Fix compile error (#1650) 2023-12-18 07:35:00 +01:00
gullradriel 0b11730835 fix wrong direction in tx freq correction (#1649)
Co-authored-by: GullCode <gullradriel@hotmail.com>
2023-12-17 18:47:20 -06:00
Bernd Herzog 6069145b68 Usb serial (#1648)
* enabled usb clock
* added usb stack to application
* fixed pll0usb clock setup
* implemented serial usb handshake
* implemented serial communication
* integrated chibios shell
* implemented device reset
* implemented enter dfu mode
* implemented hackrf mode command
* implemented flash command
* implemented memory manipulation
* implemented button control
* fixed mode change
* improved reset behavior
* implemented directory commands
* implemented file commands
* improved data communication
* refactorings
2023-12-17 17:20:35 +01:00
48 changed files with 2172 additions and 49 deletions
+1 -1
View File
@@ -1 +1 @@
v1.7.4
v1.8.0
+1 -1
View File
@@ -1 +1 @@
v1.8.0
v1.9.0
+1
View File
@@ -54,6 +54,7 @@ add_custom_target(
add_custom_target(
program
COMMAND ${PROJECT_SOURCE_DIR}/tools/enter_mode.sh hackrf
COMMAND dfu-util --device 1fc9:000c --download ${HACKRF_FIRMWARE_DFU_IMAGE} || (exit 0) # We need to add it for dfu-utils v.011 , (in v.09 it is not necessary)
COMMAND sleep 3s
COMMAND hackrf_spiflash -i -R -w ${FIRMWARE_FILENAME}
+18
View File
@@ -113,6 +113,17 @@ set(CSRC
${BOARDSRC}
${FATFSSRC}
firmware_info.c
usb_serial_cdc.c
usb_serial_descriptor.c
usb_serial_endpoints.c
usb_serial_io.c
${HACKRF_PATH}/firmware/common/usb.c
${HACKRF_PATH}/firmware/common/usb_queue.c
${HACKRF_PATH}/firmware/hackrf_usb/usb_device.c
${HACKRF_PATH}/firmware/common/usb_request.c
${HACKRF_PATH}/firmware/common/usb_standard_request.c
${CHIBIOS}/os/various/shell.c
${CHIBIOS}/os/various/chprintf.c
)
# C++ sources that can be compiled in ARM or THUMB mode depending on the global
@@ -191,6 +202,10 @@ set(CPPSRC
log_file.cpp
metadata_file.cpp
portapack.cpp
usb_serial_shell.cpp
usb_serial_event.cpp
usb_serial_thread.cpp
usb_serial.cpp
qrcodegen.cpp
radio.cpp
receiver_model.cpp
@@ -363,6 +378,9 @@ set(INCDIR ${CMAKE_CURRENT_BINARY_DIR} ${COMMON} ${PORTINC} ${KERNINC} ${TESTINC
${HALINC} ${PLATFORMINC} ${BOARDINC}
${FATFSINC}
${CHIBIOS}/os/various
${HACKRF_PATH}/firmware/libopencm3/include
${HACKRF_PATH}/firmware/common
${HACKRF_PATH}/firmware
ui
hw
apps
+9 -13
View File
@@ -436,6 +436,8 @@ BLERxView::BLERxView(NavigationView& nav)
nav_.push<BleRecentEntryDetailView>(entry);
};
usb_serial_thread = std::make_unique<UsbSerialThread>();
ensure_directory(find_packet_path);
ensure_directory(log_packets_path);
ensure_directory(packet_save_path);
@@ -684,24 +686,16 @@ bool BLERxView::saveFile(const std::filesystem::path& path) {
}
void BLERxView::on_data(BlePacketData* packet) {
std::string str_console = "";
if (!logging) {
str_log = "";
}
str_console += pdu_type_to_string((ADV_PDU_TYPE)packet->type);
str_console += " Len:";
str_console += to_string_dec_uint(packet->size);
str_console += "\n";
str_console += "Mac:";
str_console += " Mac:";
str_console += to_string_mac_address(packet->macAddress, 6, false);
str_console += "\n";
str_console += "Data:";
str_console += " Data:";
int i;
@@ -709,8 +703,6 @@ void BLERxView::on_data(BlePacketData* packet) {
str_console += to_string_hex(packet->data[i], 2);
}
str_console += "\n";
uint64_t macAddressEncoded = copy_mac_address_to_uint64(packet->macAddress);
// Start of Packet stuffing.
@@ -728,9 +720,13 @@ void BLERxView::on_data(BlePacketData* packet) {
// Log at End of Packet.
if (logger && logging) {
logger->log_raw_data(str_console);
logger->log_raw_data(str_console + "\r\n");
}
usb_serial_thread->serial_str = str_console + "\r\n";
usb_serial_thread->str_ready = true;
str_console = "";
if (!searchList.empty()) {
auto it = searchList.begin();
+4
View File
@@ -35,6 +35,7 @@
#include "radio_state.hpp"
#include "log_file.hpp"
#include "utility.hpp"
#include "usb_serial_thread.hpp"
#include "recent_entries.hpp"
@@ -194,6 +195,7 @@ class BLERxView : public View {
std::string build_line_str(BleRecentEntry entry);
void on_save_file(const std::string value);
bool saveFile(const std::filesystem::path& path);
std::unique_ptr<UsbSerialThread> usb_serial_thread{};
void on_data(BlePacketData* packetData);
void on_filter_change(std::string value);
void on_file_changed(const std::filesystem::path& new_file_path);
@@ -213,6 +215,7 @@ class BLERxView : public View {
uint8_t sort_index{0};
std::string filter{};
bool logging{false};
bool name_enable{true};
app_settings::SettingsManager settings_{
"rx_ble",
@@ -225,6 +228,7 @@ class BLERxView : public View {
{"name"sv, &name_enable},
}};
std::string str_console = "";
uint8_t console_color{0};
uint32_t prev_value{0};
uint8_t channel_number = 37;
+1 -1
View File
@@ -459,7 +459,7 @@ SetFrequencyCorrectionView::SetFrequencyCorrectionView(NavigationView& nav) {
pmem::set_freq_rx_correction_updown(v);
};
opt_tx_correction_mode.set_by_value(pmem::config_freq_rx_correction_updown());
opt_tx_correction_mode.set_by_value(pmem::config_freq_tx_correction_updown());
opt_tx_correction_mode.on_change = [this](size_t, OptionsField::value_t v) {
pmem::set_freq_tx_correction_updown(v);
};
+1 -2
View File
@@ -88,8 +88,7 @@ SubGhzDView::SubGhzDView(NavigationView& nav)
recent_entries_view.on_select = [this](const SubGhzDRecentEntry& entry) {
nav_.push<SubGhzDRecentEntryDetailView>(entry);
};
baseband::set_subghzd(0); // am
receiver_model.set_sampling_rate(4'000'000);
baseband::set_subghzd_config(0, receiver_model.sampling_rate()); // 0=am
receiver_model.enable();
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
on_tick_second();
@@ -115,8 +115,7 @@ WeatherView::WeatherView(NavigationView& nav)
recent_entries_view.on_select = [this](const WeatherRecentEntry& entry) {
nav_.push<WeatherRecentEntryDetailView>(entry);
};
baseband::set_weather();
receiver_model.set_sampling_rate(4'000'000); // needed too
baseband::set_subghzd_config(0, receiver_model.sampling_rate()); // 0=am
receiver_model.enable();
signal_token_tick_second = rtc_time::signal_tick_second += [this]() {
on_tick_second();
@@ -233,4 +232,4 @@ void RecentEntriesTable<ui::WeatherRecentEntries>::draw(
painter.draw_string(target_rect.location(), style, line);
}
} // namespace ui
} // namespace ui
@@ -100,8 +100,8 @@ class WeatherView : public View {
NavigationView& nav_;
RxRadioState radio_state_{
433'920'000 /* frequency */,
2'500'000 /* bandwidth max283x*/,
4'000'000 /* sampling rate */,
1'750'000 /* bandwidth */,
2'000'000 /* sampling rate */,
ReceiverModel::Mode::AMAudio};
app_settings::SettingsManager settings_{
"rx_weather",
+2 -7
View File
@@ -319,13 +319,8 @@ void set_spectrum_painter_config(const uint16_t width, const uint16_t height, bo
send_message(&message);
}
void set_weather() {
const SubGhzFPRxConfigureMessage message{0};
send_message(&message);
}
void set_subghzd(uint8_t modulation = 0) {
const SubGhzFPRxConfigureMessage message{modulation};
void set_subghzd_config(uint8_t modulation = 0, uint32_t sampling_rate = 0) {
const SubGhzFPRxConfigureMessage message{modulation, sampling_rate};
send_message(&message);
}
+1 -2
View File
@@ -88,8 +88,7 @@ void set_spectrum(const size_t sampling_rate, const size_t trigger);
void set_siggen_tone(const uint32_t tone);
void set_siggen_config(const uint32_t bw, const uint32_t shape, const uint32_t duration);
void set_spectrum_painter_config(const uint16_t width, const uint16_t height, bool update, int32_t bw);
void set_weather();
void set_subghzd(uint8_t modulation);
void set_subghzd_config(uint8_t modulation, uint32_t sampling_rate);
void request_beep();
void run_image(const portapack::spi_flash::image_tag_t image_tag);
+1
View File
@@ -113,6 +113,7 @@ void EventDispatcher::run() {
while (is_running) {
const auto events = wait();
dispatch(events);
portapack::usb_serial.dispatch();
}
}
+1 -1
View File
@@ -285,7 +285,7 @@
* buffers.
*/
#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
#define SERIAL_BUFFERS_SIZE 16
#define SERIAL_BUFFERS_SIZE 64
#endif
/*===========================================================================*/
+23 -4
View File
@@ -122,6 +122,8 @@ static bool touch_update() {
}
static uint8_t switches_raw = 0;
static uint8_t injected_switch = 0;
static uint8_t injected_encoder = 0;
/* The raw data is not packed in a way that makes looping over it easy.
* One option would be an accessor helper (RawSwitch). Another option
@@ -170,8 +172,11 @@ static bool encoder_update(const uint8_t raw) {
static bool encoder_read() {
const auto delta = encoder.update(
encoder_debounce[0].state(),
encoder_debounce[1].state());
encoder_debounce[0].state() | (injected_encoder == 1),
encoder_debounce[1].state() | (injected_encoder == 2));
if (injected_encoder > 0)
injected_encoder = 0;
if (delta != 0) {
encoder_position += delta;
@@ -186,10 +191,10 @@ void timer0_callback(GPTDriver* const) {
if (touch_update()) event_mask |= EVT_MASK_TOUCH;
switches_raw = swizzled_switches();
if (switches_update(switches_raw))
if (switches_update(switches_raw) || (injected_switch > 0))
event_mask |= EVT_MASK_SWITCHES;
if (encoder_update(switches_raw) && encoder_read())
if (encoder_update(switches_raw) || encoder_read())
event_mask |= EVT_MASK_ENCODER;
/* Signal event loop */
@@ -238,6 +243,13 @@ SwitchesState get_switches_state() {
for (size_t i = 0; i < result.size(); i++)
result[i] = switch_debounce[i].state();
if (injected_switch > 0 && injected_switch <= 6) {
result[injected_switch - 1] = 1;
injected_switch = 0xff;
} else if (injected_switch == 0xff) {
injected_switch = 0x00;
}
return result;
}
@@ -277,5 +289,12 @@ uint8_t switches() {
return switches_raw;
}
void inject_switch(uint8_t button) {
if (button <= 6)
injected_switch = button;
else if (button > 6)
injected_encoder = button - 6;
}
} // namespace debug
} // namespace control
+1
View File
@@ -56,6 +56,7 @@ namespace control {
namespace debug {
uint8_t switches();
void inject_switch(uint8_t);
} // namespace debug
} // namespace control
+4 -1
View File
@@ -70,6 +70,7 @@ lcd::ILI9341 display;
I2C i2c0(&I2CD0);
SPI ssp1(&SPID2);
portapack::USBSerial usb_serial;
si5351::Si5351 clock_generator{
i2c0, hackrf::one::si5351_i2c_address};
@@ -368,7 +369,7 @@ static void shutdown_base() {
*
* XTAL_OSC = powered down
*
* PLL0USB = powered down
* PLL0USB = XTAL, 480 MHz
* PLL0AUDIO = GP_CLKIN, Fcco=491.52 MHz, Fout=12.288 MHz
* PLL1 =
* OG: GP_CLKIN * 10 = 200 MHz
@@ -464,6 +465,8 @@ bool init() {
/* Remove /2P divider from PLL1 output to achieve full speed */
cgu::pll1::direct();
usb_serial.initialize();
i2c0.start(i2c_config_fast_clock);
chThdSleepMilliseconds(10);
+2
View File
@@ -31,6 +31,7 @@
#include "si5351.hpp"
#include "lcd_ili9341.hpp"
#include "backlight.hpp"
#include "usb_serial.hpp"
#include "radio.hpp"
#include "clock_manager.hpp"
@@ -46,6 +47,7 @@ extern lcd::ILI9341 display;
extern I2C i2c0;
extern SPI ssp1;
extern portapack::USBSerial usb_serial;
extern si5351::Si5351 clock_generator;
extern ClockManager clock_manager;
+97
View File
@@ -0,0 +1,97 @@
extern "C" {
#include "usb_serial_io.h"
#include "usb_serial_cdc.h"
}
#include "usb_serial_shell.hpp"
#include "usb_serial.hpp"
#include "portapack.hpp"
#include <libopencm3/cm3/common.h>
#include <libopencm3/lpc43xx/usb.h>
namespace portapack {
void USBSerial::initialize() {
enable_xtal();
disable_pll0();
setup_pll0();
enable_pll0();
setup_usb_clock();
setup_usb_serial_controller();
init_serial_usb_driver(&SUSBD1);
shellInit();
}
void USBSerial::dispatch() {
if (!connected)
return;
if (shell_created == false) {
shell_created = true;
create_shell();
}
bulk_out_receive();
}
void USBSerial::on_channel_opened() {
connected = true;
}
void USBSerial::on_channel_closed() {
connected = false;
}
void USBSerial::enable_xtal() {
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 0;
LPC_CGU->XTAL_OSC_CTRL.HF = 0;
}
void USBSerial::disable_pll0() {
LPC_CGU->PLL0USB_CTRL.PD = 1;
LPC_CGU->PLL0USB_CTRL.AUTOBLOCK = 1;
LPC_CGU->PLL0USB_CTRL.BYPASS = 0;
LPC_CGU->PLL0USB_CTRL.DIRECTI = 0;
LPC_CGU->PLL0USB_CTRL.DIRECTO = 0;
LPC_CGU->PLL0USB_CTRL.CLKEN = 0;
LPC_CGU->PLL0USB_CTRL.FRM = 0;
LPC_CGU->PLL0USB_CTRL.CLK_SEL = 0x06; // 12MHz internal XTAL
}
void USBSerial::setup_pll0() {
/* use XTAL_OSC as clock source for PLL0USB */
while (LPC_CGU->PLL0USB_STAT.LOCK) {
}
// /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */
// /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */
LPC_CGU->PLL0USB_MDIV = 0x06167FFA;
LPC_CGU->PLL0USB_NP_DIV = 0x00302062;
LPC_CGU->PLL0USB_CTRL.PD = 1;
LPC_CGU->PLL0USB_CTRL.DIRECTI = 1;
LPC_CGU->PLL0USB_CTRL.DIRECTO = 1;
LPC_CGU->PLL0USB_CTRL.CLKEN = 1;
}
void USBSerial::enable_pll0() {
// /* power on PLL0USB and wait until stable */
LPC_CGU->PLL0USB_CTRL.PD = 0;
while (!LPC_CGU->PLL0USB_STAT.LOCK) {
}
}
void USBSerial::setup_usb_clock() {
/* use PLL0USB as clock source for USB0 */
LPC_CGU->BASE_USB0_CLK.AUTOBLOCK = 1;
LPC_CGU->BASE_USB0_CLK.CLK_SEL = 0x07;
LPC_CGU->BASE_USB0_CLK.PD = 0;
}
} // namespace portapack
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
namespace portapack {
class USBSerial {
public:
void initialize();
void dispatch();
void on_channel_opened();
void on_channel_closed();
private:
void enable_xtal();
void disable_pll0();
void setup_pll0();
void enable_pll0();
void setup_usb_clock();
bool connected{false};
bool shell_created{false};
};
} // namespace portapack
+143
View File
@@ -0,0 +1,143 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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 "usb_serial_cdc.h"
#include "usb_serial_endpoints.h"
#include "usb_serial_event.hpp"
extern void usb0_isr(void);
CH_IRQ_HANDLER(USB0_IRQHandler) {
CH_IRQ_PROLOGUE();
usb0_isr();
CH_IRQ_EPILOGUE();
}
uint32_t __ldrex(volatile uint32_t* addr) {
__disable_irq();
return *addr;
}
uint32_t __strex(uint32_t val, volatile uint32_t* addr) {
(void)val;
(void)addr;
*addr = val;
__enable_irq();
return 0;
}
void nvic_enable_irq(uint8_t irqn) {
NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
}
void usb_configuration_changed(usb_device_t* const device) {
(void)device;
usb_endpoint_init(&usb_endpoint_int_in);
usb_endpoint_init(&usb_endpoint_bulk_in);
usb_endpoint_init(&usb_endpoint_bulk_out);
}
void setup_usb_serial_controller(void) {
usb_set_configuration_changed_cb(usb_configuration_changed);
usb_peripheral_reset();
usb_device_init(0, &usb_device);
usb_queue_init(&usb_endpoint_control_out_queue);
usb_queue_init(&usb_endpoint_control_in_queue);
usb_queue_init(&usb_endpoint_int_in_queue);
usb_queue_init(&usb_endpoint_bulk_out_queue);
usb_queue_init(&usb_endpoint_bulk_in_queue);
usb_endpoint_init(&usb_endpoint_control_out);
usb_endpoint_init(&usb_endpoint_control_in);
usb_run(&usb_device);
}
const usb_request_handlers_t usb_request_handlers = {
.standard = usb_standard_request,
.class = usb_class_request,
.vendor = 0,
.reserved = 0};
usb_request_status_t usb_class_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) {
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
volatile uint8_t request = endpoint->setup.request;
if (request == 0x21) // GET LINE CODING REQUEST
return usb_get_line_coding_request(endpoint, stage);
if (request == 0x22) // SET CONTROL LINE STATE REQUEST
return usb_set_control_line_state_request(endpoint, stage);
if (request == 0x20) // SET LINE CODING REQUEST
return usb_set_line_coding_request(endpoint, stage);
return USB_REQUEST_STATUS_OK;
return status;
}
usb_request_status_t usb_get_line_coding_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
0,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_set_control_line_state_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
// if (endpoint->setup.value == 3) {
on_channel_opened();
//} else {
// on_channel_closed();
//}
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_set_line_coding_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->out,
&endpoint->buffer,
32,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
usb_transfer_schedule_ack(endpoint->in);
}
return USB_REQUEST_STATUS_OK;
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
#ifndef __cplusplus
#pragma GCC diagnostic push
// external code, so ignore warnings
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include <common/usb.h>
#include <common/usb_request.h>
#include <common/usb_standard_request.h>
#include <hackrf_usb/usb_device.h>
#include <hackrf_usb/usb_endpoint.h>
#pragma GCC diagnostic pop
usb_request_status_t usb_class_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_get_line_coding_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_set_control_line_state_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_set_line_coding_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
#endif
void setup_usb_serial_controller(void);
@@ -0,0 +1,339 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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 "usb_serial_descriptor.h"
#include "usb_serial_endpoints.h"
#define USB_VENDOR_ID (0x1D50)
#define USB_PRODUCT_ID (0x6018)
#define USB_API_VERSION (0x0100)
#define USB_WORD(x) (x & 0xFF), ((x >> 8) & 0xFF)
#define USB_MAX_PACKET0 (64)
#define USB_MAX_PACKET_BULK_FS (64)
#define USB_MAX_PACKET_BULK_HS (64)
#define USB_STRING_LANGID (0x0409)
uint8_t usb_descriptor_device[] = {
18, // bLength
USB_DESCRIPTOR_TYPE_DEVICE, // bDescriptorType
USB_WORD(0x0200), // bcdUSB
0xef, // bDeviceClass
0x02, // bDeviceSubClass
0x01, // bDeviceProtocol
USB_MAX_PACKET0, // bMaxPacketSize0
USB_WORD(USB_VENDOR_ID), // idVendor
USB_WORD(USB_PRODUCT_ID), // idProduct
USB_WORD(USB_API_VERSION), // bcdDevice
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
0x01 // bNumConfigurations
};
uint8_t usb_descriptor_device_qualifier[] = {
10, // bLength
USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER, // bDescriptorType
USB_WORD(0x0200), // bcdUSB
0xef, // bDeviceClass
0x02, // bDeviceSubClass
0x01, // bDeviceProtocol
USB_MAX_PACKET0, // bMaxPacketSize0
0x01, // bNumOtherSpeedConfigurations
0x00 // bReserved
};
uint8_t usb_descriptor_configuration_full_speed[] = {
9, // bLength
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
USB_WORD((16 + 8 + 9 + 5 + 5 + 4 + 5 + 9 + 7 + 7)), // wTotalLength
0x02, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0x80, // bmAttributes: USB-powered
250, // bMaxPower: 500mA
8, // bLength
0xb, // bDescriptorType
0,
2,
0x02,
0x02,
0x00,
4,
9, // bLength
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x01, // bNumEndpoints
0x02, // bInterfaceClass: vendor-specific
0x02, // bInterfaceSubClass
0x00, // bInterfaceProtocol: vendor-specific
0x04, // iInterface
5,
0x24, // ACM
0x00,
USB_WORD(0x0110),
5,
0x24,
0x01,
0x00,
0x01,
4,
0x24,
0x02,
0x02,
5,
0x24,
0x06,
0x00,
0x01,
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_INT_IN_EP_ADDR, // bEndpointAddress
0x03, // bmAttributes: BULK
USB_WORD(16), // wMaxPacketSize
0xFF, // bInterval: no NAK
9, // bLength
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
0x01, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndpoints
0x0a, // bInterfaceClass: vendor-specific
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol: vendor-specific
0x00, // iInterface
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
0x01, // bInterval: no NAK
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_IN_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_FS), // wMaxPacketSize
0x01, // bInterval: NAK
0, // TERMINATOR
};
uint8_t usb_descriptor_configuration_high_speed[] = {
9, // bLength
USB_DESCRIPTOR_TYPE_CONFIGURATION, // bDescriptorType
USB_WORD((16 + 8 + 9 + 5 + 5 + 4 + 5 + 9 + 7 + 7)), // wTotalLength
0x02, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0x80, // bmAttributes: USB-powered
250, // bMaxPower: 500mA
8, // bLength
0xb, // bDescriptorType
0,
2,
0x02,
0x02,
0x00,
4,
9, // bLength
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x01, // bNumEndpoints
0x02, // bInterfaceClass: vendor-specific
0x02, // bInterfaceSubClass
0x00, // bInterfaceProtocol: vendor-specific
0x04, // iInterface
5,
0x24,
0x00,
USB_WORD(0x0110),
5,
0x24,
0x01,
0x00,
0x01,
4,
0x24,
0x02,
0x02,
5,
0x24,
0x06,
0x00,
0x01,
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_INT_IN_EP_ADDR, // bEndpointAddress
0x03, // bmAttributes: BULK
USB_WORD(16), // wMaxPacketSize
0xFF, // bInterval: no NAK
9, // bLength
USB_DESCRIPTOR_TYPE_INTERFACE, // bDescriptorType
0x01, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndpoints
0x0a, // bInterfaceClass: vendor-specific
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol: vendor-specific
0x00, // iInterface
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_OUT_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
0x01, // bInterval: no NAK
7, // bLength
USB_DESCRIPTOR_TYPE_ENDPOINT, // bDescriptorType
USB_BULK_IN_EP_ADDR, // bEndpointAddress
0x02, // bmAttributes: BULK
USB_WORD(USB_MAX_PACKET_BULK_HS), // wMaxPacketSize
0x01, // bInterval: NAK
0, // TERMINATOR
};
uint8_t usb_descriptor_string_languages[] = {
0x04, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
USB_WORD(USB_STRING_LANGID), // wLANGID
};
// clang-format off
uint8_t usb_descriptor_string_manufacturer[] = {
40, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'G', 0x00,
'r', 0x00,
'e', 0x00,
'a', 0x00,
't', 0x00,
' ', 0x00,
'S', 0x00,
'c', 0x00,
'o', 0x00,
't', 0x00,
't', 0x00,
' ', 0x00,
'G', 0x00,
'a', 0x00,
'd', 0x00,
'g', 0x00,
'e', 0x00,
't', 0x00,
's', 0x00,
};
uint8_t usb_descriptor_string_product[] = {
43, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'P', 0x00,
'o', 0x00,
'r', 0x00,
't', 0x00,
'a', 0x00,
'P', 0x00,
'a', 0x00,
'c', 0x00,
'k', 0x00,
' ', 0x00,
'M', 0x00,
'a', 0x00,
'y', 0x00,
'h', 0x00,
'e', 0x00,
'm', 0x00,
};
uint8_t usb_descriptor_string_config_description[] = {
24, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'T', 0x00,
'r', 0x00,
'a', 0x00,
'n', 0x00,
's', 0x00,
'c', 0x00,
'e', 0x00,
'i', 0x00,
'v', 0x00,
'e', 0x00,
'r', 0x00,
};
uint8_t usb_descriptor_string_serial_number[USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN];
uint8_t* usb_descriptor_strings[] = {
usb_descriptor_string_languages,
usb_descriptor_string_manufacturer,
usb_descriptor_string_product,
usb_descriptor_string_config_description,
usb_descriptor_string_serial_number,
0, // TERMINATOR
};
uint8_t wcid_string_descriptor[] = {
18, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
'M', 0x00,
'S', 0x00,
'F', 0x00,
'T', 0x00,
'1', 0x00,
'0', 0x00,
'0', 0x00,
USB_WCID_VENDOR_REQ, // vendor request code for further descriptor
0x00
};
uint8_t wcid_feature_descriptor[] = {
0x28, 0x00, 0x00, 0x00, // bLength
USB_WORD(0x0100), // WCID version
USB_WORD(0x0004), // WICD descriptor index
0x01, // bNumSections
0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Reserved
0x00, // bInterfaceNumber
0x01, // Reserved
'W', 'I', 'N', 'U', 'S', 'B', 0x00,0x00, // Compatible ID, padded with zeros
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // Sub-compatible ID
0x00,0x00,0x00,0x00,0x00,0x00 // Reserved
};
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
extern uint8_t usb_descriptor_device[];
extern uint8_t usb_descriptor_device_qualifier[];
extern uint8_t usb_descriptor_configuration_full_speed[];
extern uint8_t usb_descriptor_configuration_high_speed[];
extern uint8_t usb_descriptor_string_languages[];
extern uint8_t usb_descriptor_string_manufacturer[];
extern uint8_t usb_descriptor_string_product[];
#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32
#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN \
(USB_DESCRIPTOR_STRING_SERIAL_LEN * 2 + 2) /* UTF-16LE */
extern uint8_t usb_descriptor_string_serial_number[];
extern uint8_t* usb_descriptor_strings[];
#define USB_WCID_VENDOR_REQ 0x19
extern uint8_t wcid_string_descriptor[];
extern uint8_t wcid_feature_descriptor[];
@@ -0,0 +1,81 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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 "usb_serial_endpoints.h"
#pragma GCC diagnostic push
// external code, so ignore warnings
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include <common/usb.h>
#include <common/usb_request.h>
#include <common/usb_standard_request.h>
#include <hackrf_usb/usb_device.h>
#include <hackrf_usb/usb_endpoint.h>
#pragma GCC diagnostic pop
usb_endpoint_t usb_endpoint_control_out = {
.address = USB_CONTROL_OUT_EP_ADDR,
.device = &usb_device,
.in = &usb_endpoint_control_in,
.out = &usb_endpoint_control_out,
.setup_complete = usb_setup_complete,
.transfer_complete = usb_control_out_complete,
};
USB_DEFINE_QUEUE(usb_endpoint_control_out, 4);
usb_endpoint_t usb_endpoint_control_in = {
.address = USB_CONTROL_IN_EP_ADDR,
.device = &usb_device,
.in = &usb_endpoint_control_in,
.out = &usb_endpoint_control_out,
.setup_complete = 0,
.transfer_complete = usb_control_in_complete,
};
static USB_DEFINE_QUEUE(usb_endpoint_control_in, 4);
usb_endpoint_t usb_endpoint_int_in = {
.address = USB_INT_IN_EP_ADDR,
.device = &usb_device,
.in = &usb_endpoint_int_in,
.out = 0,
.setup_complete = 0,
.transfer_complete = usb_queue_transfer_complete};
static USB_DEFINE_QUEUE(usb_endpoint_int_in, 1);
usb_endpoint_t usb_endpoint_bulk_in = {
.address = USB_BULK_IN_EP_ADDR,
.device = &usb_device,
.in = &usb_endpoint_bulk_in,
.out = 0,
.setup_complete = 0,
.transfer_complete = usb_queue_transfer_complete};
static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 1);
usb_endpoint_t usb_endpoint_bulk_out = {
.address = USB_BULK_OUT_EP_ADDR,
.device = &usb_device,
.in = 0,
.out = &usb_endpoint_bulk_out,
.setup_complete = 0,
.transfer_complete = usb_queue_transfer_complete};
static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 1);
@@ -0,0 +1,51 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
#include <usb_type.h>
#include <usb_queue.h>
#define USB_CONTROL_IN_EP_ADDR (0x80)
#define USB_CONTROL_OUT_EP_ADDR (0x00)
#define USB_INT_IN_EP_ADDR (0x82)
#define USB_BULK_OUT_EP_ADDR (0x01)
#define USB_BULK_IN_EP_ADDR (0x81)
extern usb_endpoint_t usb_endpoint_control_out;
extern USB_DECLARE_QUEUE(usb_endpoint_control_out);
extern usb_endpoint_t usb_endpoint_control_in;
extern USB_DECLARE_QUEUE(usb_endpoint_control_in);
extern usb_endpoint_t usb_endpoint_int_in;
extern USB_DECLARE_QUEUE(usb_endpoint_int_in);
extern usb_endpoint_t usb_endpoint_bulk_in;
extern USB_DECLARE_QUEUE(usb_endpoint_bulk_in);
extern usb_endpoint_t usb_endpoint_bulk_out;
extern USB_DECLARE_QUEUE(usb_endpoint_bulk_out);
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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 "usb_serial_event.hpp"
#include "portapack.hpp"
extern "C" {
void on_channel_opened() {
portapack::usb_serial.on_channel_opened();
}
void on_channel_closed() {
portapack::usb_serial.on_channel_closed();
}
}
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
#ifdef __cplusplus
extern "C" {
#endif
void on_channel_opened(void);
void on_channel_closed(void);
#ifdef __cplusplus
}
#endif
+144
View File
@@ -0,0 +1,144 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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 "usb_serial_io.h"
#include "usb_serial_endpoints.h"
#pragma GCC diagnostic push
// external code, so ignore warnings
#pragma GCC diagnostic ignored "-Wstrict-prototypes"
#include <common/usb.h>
#include <common/usb_request.h>
#include <common/usb_standard_request.h>
#include <hackrf_usb/usb_device.h>
#include <hackrf_usb/usb_endpoint.h>
#pragma GCC diagnostic pop
#include <usb_request.h>
#include <string.h>
SerialUSBDriver SUSBD1;
void bulk_out_receive(void) {
int ret;
do {
ret = usb_transfer_schedule(
&usb_endpoint_bulk_out,
&usb_endpoint_bulk_out.buffer[0],
32,
serial_bulk_transfer_complete,
NULL);
} while (ret != -1);
}
void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred) {
(void)user_data;
chSysLockFromIsr();
for (unsigned int i = 0; i < bytes_transferred; i++) {
msg_t ret;
do {
ret = chIQPutI(&SUSBD1.iqueue, usb_endpoint_bulk_out.buffer[i]);
if (ret == Q_FULL)
chThdSleepMilliseconds(1);
} while (ret == Q_FULL);
}
chSysUnlockFromIsr();
}
static void onotify(GenericQueue* qp) {
SerialUSBDriver* sdp = chQGetLink(qp);
uint8_t buff[64];
int n = chOQGetFullI(&sdp->oqueue);
if (n > 64) n = 64; // don't overflow
if (n > 0) {
for (int i = 0; i < n; i++) {
buff[i] = chOQGetI(&sdp->oqueue);
}
int ret;
chSysUnlock();
do {
ret = usb_transfer_schedule(
&usb_endpoint_bulk_in,
&buff[0],
n,
NULL,
NULL);
if (ret == -1)
chThdSleepMilliseconds(1);
} while (ret == -1);
chSysLock();
}
}
static size_t write(void* ip, const uint8_t* bp, size_t n) {
return chOQWriteTimeout(&((SerialUSBDriver*)ip)->oqueue, bp,
n, TIME_INFINITE);
}
static size_t read(void* ip, uint8_t* bp, size_t n) {
return chIQReadTimeout(&((SerialUSBDriver*)ip)->iqueue, bp,
n, TIME_INFINITE);
}
static msg_t put(void* ip, uint8_t b) {
return chOQPutTimeout(&((SerialUSBDriver*)ip)->oqueue, b, TIME_INFINITE);
}
static msg_t get(void* ip) {
return chIQGetTimeout(&((SerialUSBDriver*)ip)->iqueue, TIME_INFINITE);
}
static msg_t putt(void* ip, uint8_t b, systime_t timeout) {
return chOQPutTimeout(&((SerialUSBDriver*)ip)->oqueue, b, timeout);
}
static msg_t gett(void* ip, systime_t timeout) {
return chIQGetTimeout(&((SerialUSBDriver*)ip)->iqueue, timeout);
}
static size_t writet(void* ip, const uint8_t* bp, size_t n, systime_t time) {
return chOQWriteTimeout(&((SerialUSBDriver*)ip)->oqueue, bp, n, time);
}
static size_t readt(void* ip, uint8_t* bp, size_t n, systime_t time) {
return chIQReadTimeout(&((SerialUSBDriver*)ip)->iqueue, bp, n, time);
}
static const struct SerialUSBDriverVMT vmt = {
write, read, put, get,
putt, gett, writet, readt};
void init_serial_usb_driver(SerialUSBDriver* sdp) {
sdp->vmt = &vmt;
chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, NULL, sdp);
chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp);
}
+46
View File
@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
struct SerialUSBDriverVMT {
_base_asynchronous_channel_methods
};
struct SerialUSBDriver {
/** @brief Virtual Methods Table.*/
const struct SerialUSBDriverVMT* vmt;
InputQueue iqueue; /* Output queue.*/
OutputQueue oqueue; /* Input circular buffer.*/
uint8_t ib[SERIAL_BUFFERS_SIZE]; /* Output circular buffer.*/
uint8_t ob[SERIAL_BUFFERS_SIZE];
};
typedef struct SerialUSBDriver SerialUSBDriver;
extern SerialUSBDriver SUSBD1;
void init_serial_usb_driver(SerialUSBDriver* sdp);
void bulk_out_receive(void);
void serial_bulk_transfer_complete(void* user_data, unsigned int bytes_transferred);
+510
View File
@@ -0,0 +1,510 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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 "usb_serial_shell.hpp"
#include "event_m0.hpp"
#include "baseband_api.hpp"
#include "core_control.hpp"
#include "bitmap.hpp"
#include "png_writer.hpp"
#include "irq_controls.hpp"
#include "usb_serial_io.h"
#include "ff.h"
#include "chprintf.h"
#include "chqueues.h"
#include <string>
#include <codecvt>
#include <cstring>
#include <locale>
#define SHELL_WA_SIZE THD_WA_SIZE(1024 * 3)
#define palOutputPad(port, pad) (LPC_GPIO->DIR[(port)] |= 1 << (pad))
// queue handler from ch
static msg_t qwait(GenericQueue* qp, systime_t time) {
if (TIME_IMMEDIATE == time)
return Q_TIMEOUT;
currp->p_u.wtobjp = qp;
queue_insert(currp, &qp->q_waiting);
return chSchGoSleepTimeoutS(THD_STATE_WTQUEUE, time);
}
// This function fills the output buffer, and sends all data in 1 packet
static size_t fillOBuffer(OutputQueue* oqp, const uint8_t* bp, size_t n) {
qnotify_t nfy = oqp->q_notify;
size_t w = 0;
chDbgCheck(n > 0, "chOQWriteTimeout");
chSysLock();
while (TRUE) {
while (chOQIsFullI(oqp)) {
if (qwait((GenericQueue*)oqp, TIME_INFINITE) != Q_OK) {
chSysUnlock();
return w;
}
}
while (!chOQIsFullI(oqp) && n > 0) {
oqp->q_counter--;
*oqp->q_wrptr++ = *bp++;
if (oqp->q_wrptr >= oqp->q_top)
oqp->q_wrptr = oqp->q_buffer;
w++;
--n;
}
if (nfy) nfy(oqp);
chSysUnlock(); /* Gives a preemption chance in a controlled point.*/
if (n == 0) return w;
chSysLock();
}
}
static void cmd_reboot(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)chp;
(void)argc;
(void)argv;
m4_request_shutdown();
chThdSleepMilliseconds(50);
LPC_RGU->RESET_CTRL[0] = (1 << 0);
}
static void cmd_dfu(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)chp;
(void)argc;
(void)argv;
m4_request_shutdown();
chThdSleepMilliseconds(50);
LPC_SCU->SFSP2_8 = (LPC_SCU->SFSP2_8 & ~(7)) | 4;
palOutputPad(5, 7);
palSetPad(5, 7);
LPC_RGU->RESET_CTRL[0] = (1 << 0);
}
static void cmd_hackrf(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)chp;
(void)argc;
(void)argv;
m4_request_shutdown();
chThdSleepMilliseconds(50);
EventDispatcher::request_stop();
}
static void cmd_sd_over_usb(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)chp;
(void)argc;
(void)argv;
ui::Painter painter;
painter.fill_rectangle(
{0, 0, portapack::display.width(), portapack::display.height()},
ui::Color::black());
painter.draw_bitmap(
{portapack::display.width() / 2 - 8, portapack::display.height() / 2 - 8},
ui::bitmap_icon_hackrf,
ui::Color::yellow(),
ui::Color::black());
sdcDisconnect(&SDCD1);
sdcStop(&SDCD1);
m4_request_shutdown();
chThdSleepMilliseconds(50);
portapack::shutdown(true);
m4_init(portapack::spi_flash::image_tag_usb_sd, portapack::memory::map::m4_code, false);
m0_halt();
}
std::filesystem::path path_from_string8(char* path) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> conv;
return conv.from_bytes(path);
}
static void cmd_flash(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "Usage: flash /FIRMWARE/portapack-h1_h2-mayhem.bin\r\n");
return;
}
auto path = path_from_string8(argv[0]);
size_t filename_length = strlen(argv[0]);
if (!std::filesystem::file_exists(path)) {
chprintf(chp, "file not found.\r\n");
return;
}
std::memcpy(&shared_memory.bb_data.data[0], path.c_str(), (filename_length + 1) * 2);
m4_request_shutdown();
chThdSleepMilliseconds(50);
m4_init(portapack::spi_flash::image_tag_flash_utility, portapack::memory::map::m4_code, false);
m0_halt();
}
static void cmd_screenshot(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
ensure_directory("SCREENSHOTS");
auto path = next_filename_matching_pattern(u"SCREENSHOTS/SCR_????.PNG");
if (path.empty())
return;
PNGWriter png;
auto error = png.create(path);
if (error)
return;
for (int i = 0; i < ui::screen_height; i++) {
std::array<ui::ColorRGB888, ui::screen_width> row;
portapack::display.read_pixels({0, i, ui::screen_width, 1}, row);
png.write_scanline(row);
}
chprintf(chp, "generated %s\r\n", path.string().c_str());
}
// gives full color.
static void cmd_screenframe(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
for (int i = 0; i < ui::screen_height; i++) {
std::array<ui::ColorRGB888, ui::screen_width> row;
portapack::display.read_pixels({0, i, ui::screen_width, 1}, row);
for (int px = 0; px < ui::screen_width; px += 5) {
char buffer[5 * 3 * 2];
sprintf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", row[px].r, row[px].g, row[px].b, row[px + 1].r, row[px + 1].g, row[px + 1].b, row[px + 2].r, row[px + 2].g, row[px + 2].b, row[px + 3].r, row[px + 3].g, row[px + 3].b, row[px + 4].r, row[px + 4].g, row[px + 4].b);
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)buffer, 5 * 3 * 2);
}
chprintf(chp, "\r\n");
}
chprintf(chp, "ok\r\n");
}
static char getChrFromRgb(uint8_t r, uint8_t g, uint8_t b) {
uint8_t chR = r >> 6; // 3bit
uint8_t chG = g >> 6; // 3bit
uint8_t chB = b >> 6; // 3bit
uint8_t res = chR << 4 | chG << 2 | chB;
res += 32;
return res;
}
// sends only 1 byte (printable only) per pixel, so around 96 colors
static void cmd_screenframeshort(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argc;
(void)argv;
for (int y = 0; y < ui::screen_height; y++) {
std::array<ui::ColorRGB888, ui::screen_width> row;
portapack::display.read_pixels({0, y, ui::screen_width, 1}, row);
for (int px = 0; px < ui::screen_width; px += 60) {
char buffer[60];
for (int i = 0; i < 60; ++i) {
buffer[i] = getChrFromRgb(row[px + i].r, row[px + i].g, row[px + i].b);
}
fillOBuffer(&((SerialUSBDriver*)chp)->oqueue, (const uint8_t*)buffer, 60);
}
chprintf(chp, "\r\n");
}
chprintf(chp, "ok\r\n");
}
static void cmd_write_memory(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 2) {
chprintf(chp, "usage: write_memory <address> <value (1 or 4 bytes)>\r\n");
chprintf(chp, "example: write_memory 0x40004008 0x00000002\r\n");
return;
}
int value_length = strlen(argv[1]);
if (value_length != 10 && value_length != 4) {
chprintf(chp, "usage: write_memory <address> <value (1 or 4 bytes)>\r\n");
chprintf(chp, "example: write_memory 0x40004008 0x00000002\r\n");
return;
}
uint32_t address = (uint32_t)strtol(argv[0], NULL, 16);
uint32_t value = (uint32_t)strtol(argv[1], NULL, 16);
if (value_length == 10) {
uint32_t* data_pointer = (uint32_t*)address;
*data_pointer = value;
} else {
uint8_t* data_pointer = (uint8_t*)address;
*data_pointer = (uint8_t)value;
}
chprintf(chp, "ok\r\n");
}
static void cmd_read_memory(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: read_memory 0x40004008\r\n");
return;
}
int address = (int)strtol(argv[0], NULL, 16);
uint32_t* data_pointer = (uint32_t*)address;
chprintf(chp, "%x\r\n", *data_pointer);
}
static void cmd_button(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: button 1\r\n");
return;
}
int button = (int)strtol(argv[0], NULL, 10);
if (button < 1 || button > 8) {
chprintf(chp, "usage: button <number 1 to 8>\r\n");
return;
}
control::debug::inject_switch(button);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_list_dir(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: ls /\r\n");
return;
}
auto path = path_from_string8(argv[0]);
for (const auto& entry : std::filesystem::directory_iterator(path, "*")) {
if (std::filesystem::is_directory(entry.status())) {
chprintf(chp, "%s/\r\n", entry.path().string().c_str());
} else if (std::filesystem::is_regular_file(entry.status())) {
chprintf(chp, "%s\r\n", entry.path().string().c_str());
} else {
chprintf(chp, "%s *\r\n", entry.path().string().c_str());
}
}
}
static void cmd_sd_delete(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: rm <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
if (!std::filesystem::file_exists(path)) {
chprintf(chp, "file not found.\r\n");
return;
}
delete_file(path);
chprintf(chp, "ok\r\n");
}
File* shell_file = nullptr;
static void cmd_sd_filesize(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: filesize <path>\r\n");
return;
}
auto path = path_from_string8(argv[0]);
FILINFO res;
auto stat = f_stat(path.tchar(), &res);
if (stat == FR_OK) {
chprintf(chp, "%lu\r\n", res.fsize);
chprintf(chp, "ok\r\n");
} else {
chprintf(chp, "error\r\n");
}
}
static void cmd_sd_open(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: open <path>\r\n");
return;
}
if (shell_file != nullptr) {
chprintf(chp, "file already open\r\n");
return;
}
auto path = path_from_string8(argv[0]);
shell_file = new File();
shell_file->open(path, false, true);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_seek(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: seek <offset>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int address = (int)strtol(argv[0], NULL, 10);
shell_file->seek(address);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_close(BaseSequentialStream* chp, int argc, char* argv[]) {
(void)argv;
if (argc != 0) {
chprintf(chp, "usage: close\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
delete shell_file;
shell_file = nullptr;
chprintf(chp, "ok\r\n");
}
static void cmd_sd_read(BaseSequentialStream* chp, int argc, char* argv[]) {
if (argc != 1) {
chprintf(chp, "usage: read <number of bytes>\r\n");
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
int size = (int)strtol(argv[0], NULL, 10);
uint8_t buffer[16];
do {
File::Size bytes_to_read = size > 16 ? 16 : size;
auto bytes_read = shell_file->read(buffer, bytes_to_read);
if (bytes_read.is_error()) {
chprintf(chp, "error %d\r\n", bytes_read.error());
return;
}
for (size_t i = 0; i < bytes_read.value(); i++)
chprintf(chp, "%02X", buffer[i]);
chprintf(chp, "\r\n");
if (bytes_to_read != bytes_read.value())
return;
size -= bytes_to_read;
} while (size > 0);
chprintf(chp, "ok\r\n");
}
static void cmd_sd_write(BaseSequentialStream* chp, int argc, char* argv[]) {
const char* usage = "usage: write 0123456789ABCDEF\r\n";
if (argc != 1) {
chprintf(chp, usage);
return;
}
if (shell_file == nullptr) {
chprintf(chp, "no open file\r\n");
return;
}
size_t data_string_len = strlen(argv[0]);
if (data_string_len % 2 != 0) {
chprintf(chp, usage);
return;
}
for (size_t i = 0; i < data_string_len; i++) {
char c = argv[0][i];
if ((c < '0' || c > '9') && (c < 'A' || c > 'F')) {
chprintf(chp, usage);
return;
}
}
char buffer[3] = {0, 0, 0};
for (size_t i = 0; i < data_string_len / 2; i++) {
buffer[0] = argv[0][i * 2];
buffer[1] = argv[0][i * 2 + 1];
uint8_t value = (uint8_t)strtol(buffer, NULL, 16);
shell_file->write(&value, 1);
}
chprintf(chp, "ok\r\n");
}
static const ShellCommand commands[] = {
{"reboot", cmd_reboot},
{"dfu", cmd_dfu},
{"hackrf", cmd_hackrf},
{"sd_over_usb", cmd_sd_over_usb},
{"flash", cmd_flash},
{"screenshot", cmd_screenshot},
{"screenframe", cmd_screenframe},
{"screenframeshort", cmd_screenframeshort},
{"write_memory", cmd_write_memory},
{"read_memory", cmd_read_memory},
{"button", cmd_button},
{"ls", cmd_sd_list_dir},
{"rm", cmd_sd_delete},
{"open", cmd_sd_open},
{"seek", cmd_sd_seek},
{"close", cmd_sd_close},
{"read", cmd_sd_read},
{"write", cmd_sd_write},
{"filesize", cmd_sd_filesize},
{NULL, NULL}};
static const ShellConfig shell_cfg1 = {
(BaseSequentialStream*)&SUSBD1,
commands};
void create_shell() {
shellCreate(&shell_cfg1, SHELL_WA_SIZE, NORMALPRIO);
}
+29
View File
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2023 Bernd Herzog
*
* 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.
*/
#pragma once
#include "ch.h"
#include "hal.h"
#include "shell.h"
void create_shell(void);
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
*
* 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 "usb_serial_thread.hpp"
#include "buffer_exchange.hpp"
// UsbSerialThread //////////////////////////////////////////////////////////
UsbSerialThread::UsbSerialThread() {
create_thread();
}
UsbSerialThread::~UsbSerialThread() {
stop();
}
void UsbSerialThread::create_thread() {
thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, UsbSerialThread::static_fn, this);
}
void UsbSerialThread::stop() {
if (thread) {
chThdTerminate(thread);
chThdWait(thread);
thread = nullptr;
}
}
msg_t UsbSerialThread::static_fn(void* arg) {
auto obj = static_cast<UsbSerialThread*>(arg);
obj->run();
return 0;
}
void UsbSerialThread::run() {
while (!chThdShouldTerminate()) {
if (str_ready) {
str_ready = false;
chprintf((BaseSequentialStream*)&SUSBD1, serial_str.c_str());
}
chThdSleepMilliseconds(50);
}
}
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
*
* 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 __USB_SERIAL_THREAD_H__
#define __USB_SERIAL_THREAD_H__
#include "ch.h"
#include "event_m0.hpp"
#include "io.hpp"
#include "optional.hpp"
#include "chprintf.h"
#include "usb_serial_io.h"
#include <cstdint>
#include <cstddef>
#include <utility>
class UsbSerialThread {
public:
UsbSerialThread();
~UsbSerialThread();
void stop();
UsbSerialThread(const UsbSerialThread&) = delete;
UsbSerialThread(UsbSerialThread&&) = delete;
UsbSerialThread& operator=(const UsbSerialThread&) = delete;
UsbSerialThread& operator=(UsbSerialThread&&) = delete;
bool str_ready = false;
std::string serial_str{};
private:
Thread* thread{nullptr};
static msg_t static_fn(void* arg);
void run();
void create_thread();
};
#endif /*__CAPTURE_THREAD_H__*/
+2
View File
@@ -58,6 +58,8 @@ int main() {
f_close(&firmware_file);
LPC_RGU->RESET_CTRL[0] = (1 << 0);
while (1)
__WFE();
+7 -1
View File
@@ -47,7 +47,7 @@ void SubGhzDProcessor::execute(const buffer_c8_t& buffer) {
tm += mag;
if (meashl == currentHiLow && currentDuration < 30'000'000) // allow pass 'end' signal
{
if (currentDuration < UINT32_MAX) currentDuration += nsPerDecSamp;
currentDuration += nsPerDecSamp;
} else { // called on change, so send the last duration and dir.
if (protoList) protoList->feed(currentHiLow, currentDuration / 1000);
currentDuration = nsPerDecSamp;
@@ -74,6 +74,12 @@ void SubGhzDProcessor::configure(const SubGhzFPRxConfigureMessage& message) {
// constexpr size_t decim_0_output_fs = baseband_fs / decim_0.decimation_factor; //unused
// constexpr size_t decim_1_output_fs = decim_0_output_fs / decim_1.decimation_factor; //unused
modulation = message.modulation; // TODO: add support for FM (currently AM only)
baseband_fs = message.sampling_rate;
baseband_thread.set_sampling_rate(baseband_fs);
nsPerDecSamp = 1'000'000'000 / baseband_fs * 8; // Scaled it due to less array buffer sampes due to /8 decimation. 250 nseg (4Mhz) * 8
decim_0.configure(taps_200k_wfm_decim_0.taps);
decim_1.configure(taps_200k_wfm_decim_1.taps);
+3 -2
View File
@@ -40,8 +40,9 @@ class SubGhzDProcessor : public BasebandProcessor {
void on_message(const Message* const message) override;
private:
static constexpr size_t baseband_fs = 4'000'000; // it works, I think we need to write that master clock in the baseband_threat , even later we decimate it.
static constexpr uint32_t nsPerDecSamp = 1'000'000'000 / baseband_fs * 8; // 10 exp9/baseband_fs * 8
size_t baseband_fs = 0; // will be set later by configure message
uint32_t nsPerDecSamp = 0;
uint8_t modulation = 0;
/* Array Buffer aux. used in decim0 and decim1 IQ c16 signed data ; (decim0 defines the max length of the array) */
std::array<complex16_t, 512> dst{}; // decim0 /4 , 2048/4 = 512 complex I,Q
+5 -2
View File
@@ -47,7 +47,7 @@ void WeatherProcessor::execute(const buffer_c8_t& buffer) {
tm += mag;
if (meashl == currentHiLow && currentDuration < 30'000'000) // allow pass 'end' signal
{
if (currentDuration < UINT32_MAX) currentDuration += nsPerDecSamp;
currentDuration += nsPerDecSamp;
} else { // called on change, so send the last duration and dir.
if (protoList) protoList->feed(currentHiLow, currentDuration / 1000);
currentDuration = nsPerDecSamp;
@@ -71,9 +71,12 @@ void WeatherProcessor::on_message(const Message* const message) {
}
void WeatherProcessor::configure(const SubGhzFPRxConfigureMessage& message) {
baseband_fs = message.sampling_rate;
baseband_thread.set_sampling_rate(baseband_fs);
nsPerDecSamp = 1'000'000'000 / baseband_fs * 8; // Scaled it due to less array buffer sampes due to /8 decimation. 250 nseg (4Mhz) * 8
// constexpr size_t decim_0_output_fs = baseband_fs / decim_0.decimation_factor; //unused
// constexpr size_t decim_1_output_fs = decim_0_output_fs / decim_1.decimation_factor; //unused
(void)message; // unused
decim_0.configure(taps_200k_wfm_decim_0.taps);
decim_1.configure(taps_200k_wfm_decim_1.taps);
+2 -2
View File
@@ -40,8 +40,8 @@ class WeatherProcessor : public BasebandProcessor {
void on_message(const Message* const message) override;
private:
static constexpr size_t baseband_fs = 4'000'000; // it works, I think we need to write that master clock in the baseband_threat , even later we decimate it.
static constexpr uint32_t nsPerDecSamp = 1'000'000'000 / baseband_fs * 8; // Scaled it due to less array buffer sampes due to /8 decimation. 250 nseg (4Mhz) * 8
size_t baseband_fs = 0; // will be set later by configure message.
uint32_t nsPerDecSamp = 0;
/* Array Buffer aux. used in decim0 and decim1 IQ c16 signed data ; (decim0 defines the max length of the array) */
std::array<complex16_t, 512> dst{}; // decim0 /4 , 2048/4 = 512 complex I,Q
+14
View File
@@ -22,6 +22,9 @@
#include "scsi.h"
#include "diskio.h"
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/rgu.h>
#include <libopencm3/lpc43xx/wwdt.h>
volatile bool usb_bulk_block_done = false;
@@ -281,6 +284,17 @@ void scsi_command(msd_cbw_t* msd_cbw_data) {
case SCSI_CMD_VERIFY_10:
status = 0;
break;
case SCSI_CMD_START_STOP_UNIT:
SCU_SFSP2_8 = (SCU_SFSP2_8 & ~(7)) | 4;
struct gpio_t dfu = GPIO(5, 7);
gpio_output(&dfu);
gpio_clear(&dfu);
delay(50 * 40800);
RESET_CTRL0 = (1 << 0);
break;
}
usb_send_csw(msd_cbw_data, status);
+1 -1
View File
@@ -36,7 +36,7 @@ usb_request_status_t report_max_lun(
1,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
usb_transfer_schedule_ack(endpoint->out);
scsi_running = true;
+3 -2
View File
@@ -1241,10 +1241,11 @@ class SpectrumPainterBufferConfigureResponseMessage : public Message {
class SubGhzFPRxConfigureMessage : public Message {
public:
constexpr SubGhzFPRxConfigureMessage(uint8_t modulation = 0)
: Message{ID::SubGhzFPRxConfigure}, modulation{modulation} {
constexpr SubGhzFPRxConfigureMessage(uint8_t modulation = 0, uint32_t sampling_rate = 0)
: Message{ID::SubGhzFPRxConfigure}, modulation{modulation}, sampling_rate{sampling_rate} {
}
uint8_t modulation = 0; // 0 am, 1 fm
uint32_t sampling_rate = 0;
};
class WeatherDataMessage : public Message {
+2
View File
@@ -28,8 +28,10 @@
#include <cstddef>
#include <algorithm>
#include "chprintf.h"
#include "irq_controls.hpp"
#include "string_format.hpp"
#include "usb_serial_io.h"
using namespace portapack;
+9
View File
@@ -26,6 +26,15 @@
try=1
while [ $try -le 180 ]
do
if [ -c /dev/ttyACM0 ];
then
echo "" > /dev/ttyACM0
sleep 1
echo "sd_over_usb" > /dev/ttyACM0
sleep 5
fi
if ls /dev/disk/by-id/*Portapack*part1 1> /dev/null 2>&1; then
disk=$(ls /dev/disk/by-id/*Portapack*part1)
part=$(readlink -f $disk)
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
#
# Copyright (C) 2023 Bernd Herzog
#
# 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.
#
# This script will copy compiled external apps to the Portapack.
mode=$1
echo "entering mode $mode"
if [ -c /dev/ttyACM0 ];
then
echo "" > /dev/ttyACM0
sleep 1
echo "$mode" > /dev/ttyACM0
fi
+1 -1
View File
@@ -43,7 +43,6 @@ set(SRC_M4
${PATH_HACKRF_USB}/usb_descriptor.c
${PATH_HACKRF_USB}/usb_device.c
${PATH_HACKRF_USB}/usb_endpoint.c
${PATH_HACKRF_USB}/usb_api_board_info.c
${PATH_HACKRF_USB}/usb_api_cpld.c
${PATH_HACKRF_USB}/usb_api_m0_state.c
${PATH_HACKRF_USB}/usb_api_register.c
@@ -71,6 +70,7 @@ set(SRC_M0 ${PATH_HACKRF_USB}/sgpio_m0.s)
if(BOARD STREQUAL "HACKRF_ONE")
SET(SRC_M4
${SRC_M4}
usb_api_board_info.c
portapack.c
"${PATH_HACKRF_FIRMWARE_COMMON}/ui_portapack.c"
)
+189
View File
@@ -0,0 +1,189 @@
/*
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
* Copyright 2012 Jared Boone
* Copyright 2013 Benjamin Vernoux
*
* This file is part of HackRF.
*
* 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 "usb_api_board_info.h"
#include "platform_detect.h"
#include "firmware_info.h"
#include <hackrf_core.h>
#include <rom_iap.h>
#include <usb_queue.h>
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/rgu.h>
#include <libopencm3/lpc43xx/wwdt.h>
#include <stddef.h>
#include <string.h>
#ifdef HACKRF_ONE
#include "gpio_lpc.h"
static struct gpio_t gpio_h1r9_clkout_en = GPIO(0, 9);
static struct gpio_t gpio_h1r9_mcu_clk_en = GPIO(0, 8);
static struct gpio_t gpio_h1r9_rx = GPIO(0, 7);
#endif
usb_request_status_t usb_vendor_request_read_board_id(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
endpoint->buffer[0] = detected_platform();
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_vendor_request_read_version_string(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) {
uint8_t length;
if (stage == USB_TRANSFER_STAGE_SETUP) {
length = (uint8_t)strlen(firmware_info.version_string);
// The USB peripheral doesn't seem to be able to read directly from flash,
// so copy the version string into ram first.
memcpy(&endpoint->buffer,
firmware_info.version_string,
sizeof(firmware_info.version_string));
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;
}
static read_partid_serialno_t read_partid_serialno;
usb_request_status_t usb_vendor_request_read_partid_serialno(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) {
uint8_t length;
iap_cmd_res_t iap_cmd_res;
if (stage == USB_TRANSFER_STAGE_SETUP) {
/* Read IAP Part Number Identification */
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_PART_ID_NO;
iap_cmd_call(&iap_cmd_res);
if (iap_cmd_res.status_res.status_ret != CMD_SUCCESS) {
return USB_REQUEST_STATUS_STALL;
}
read_partid_serialno.part_id[0] = iap_cmd_res.status_res.iap_result[0];
read_partid_serialno.part_id[1] = iap_cmd_res.status_res.iap_result[1];
/* Read IAP Serial Number Identification */
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO;
iap_cmd_call(&iap_cmd_res);
if (iap_cmd_res.status_res.status_ret != CMD_SUCCESS) {
return USB_REQUEST_STATUS_STALL;
}
read_partid_serialno.serial_no[0] = iap_cmd_res.status_res.iap_result[0];
read_partid_serialno.serial_no[1] = iap_cmd_res.status_res.iap_result[1];
read_partid_serialno.serial_no[2] = iap_cmd_res.status_res.iap_result[2];
read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3];
length = (uint8_t)sizeof(read_partid_serialno_t);
usb_transfer_schedule_block(
endpoint->in,
&read_partid_serialno,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_vendor_request_reset(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
#ifdef HACKRF_ONE
/*
* Set boot pins as inputs so that the bootloader reads them
* correctly after the reset.
*/
if (detected_platform() == BOARD_ID_HACKRF1_R9) {
gpio_input(&gpio_h1r9_mcu_clk_en);
gpio_input(&gpio_h1r9_clkout_en);
gpio_input(&gpio_h1r9_rx);
}
#endif
usb_transfer_schedule_ack(endpoint->in);
delay(50 * 40800);
SCU_SFSP2_8 = (SCU_SFSP2_8 & ~(7)) | 4;
struct gpio_t dfu = GPIO(5, 7);
gpio_output(&dfu);
gpio_clear(&dfu);
wwdt_reset(100000);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_vendor_request_read_board_rev(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
endpoint->buffer[0] = detected_revision();
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;
}
usb_request_status_t usb_vendor_request_read_supported_platform(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) {
if (stage == USB_TRANSFER_STAGE_SETUP) {
uint32_t platform = supported_platform();
endpoint->buffer[0] = (platform >> 24) & 0xff;
endpoint->buffer[1] = (platform >> 16) & 0xff;
endpoint->buffer[2] = (platform >> 8) & 0xff;
endpoint->buffer[3] = platform & 0xff;
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
4,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Copyright 2012-2022 Great Scott Gadgets <info@greatscottgadgets.com>
* Copyright 2012 Jared Boone
* Copyright 2013 Benjamin Vernoux
*
* This file is part of HackRF.
*
* 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 __USB_API_BOARD_INFO_H__
#define __USB_API_BOARD_INFO_H__
#include <stdint.h>
#include <usb_type.h>
#include <usb_request.h>
typedef struct {
uint32_t part_id[2];
uint32_t serial_no[4];
} read_partid_serialno_t;
usb_request_status_t usb_vendor_request_read_board_id(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_version_string(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_partid_serialno(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_reset(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_board_rev(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_supported_platform(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_BOARD_INFO_H__ */