Merge pull request #1112 from martinling/code-style

Standardise and enforce code style
This commit is contained in:
Michael Ossmann
2022-08-15 16:17:04 -04:00
committed by GitHub
127 changed files with 8181 additions and 6076 deletions

80
.clang-format Normal file
View File

@ -0,0 +1,80 @@
# clang-format configuration file. Intended for clang-format >= 14.
#
# For more information, see:
#
# Documentation/process/clang-format.rst
# https://clang.llvm.org/docs/ClangFormat.html
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
---
AlignAfterOpenBracket: AlwaysBreak
AlignArrayOfStructures: None
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignConsecutiveMacros: true
AlignEscapedNewlines: Left
AlignOperands: DontAlign
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AttributeMacros: ['ADDAPI', 'ADDCALL']
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterStruct: false
AfterUnion: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: false
BreakStringLiterals: false
ColumnLimit: 90
ContinuationIndentWidth: 8
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '.*'
Priority: 1
IndentCaseLabels: false
IndentGotoLabels: false
IndentPPDirectives: BeforeHash
IndentWidth: 8
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
PenaltyBreakAssignment: 0
PenaltyBreakBeforeFirstCallParameter: 0
PenaltyBreakOpenParenthesis: 0
PenaltyExcessCharacter: 100
PenaltyReturnTypeOnItsOwnLine: 1000
PointerAlignment: Left
ReflowComments: false
SeparateDefinitionBlocks: Always
SortIncludes: false
SpaceAfterCStyleCast: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 8
UseTab: ForContinuationAndIndentation
...

View File

@ -0,0 +1,25 @@
name: Check code style
on: [push, pull_request]
jobs:
formatting-check:
name: clang-format
runs-on: ubuntu-latest
strategy:
matrix:
path:
- check: 'host/libhackrf/src'
exclude: ''
- check: 'host/hackrf-tools/src'
exclude: ''
- check: 'firmware/common'
exclude: 'firmware/common/xapp058'
- check: 'firmware/hackrf_usb'
exclude: ''
steps:
- uses: actions/checkout@v2
- name: Run clang-format-action
uses: jidicula/clang-format-action@v4.6.2
with:
clang-format-version: '14'
check-path: ${{ matrix.path['check'] }}
exclude-regex: ${{ matrix.path['exclude'] }}

View File

@ -21,7 +21,10 @@
#include "bitband.h" #include "bitband.h"
volatile uint32_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number) { volatile uint32_t* peripheral_bitband_address(
volatile void* const address,
const uint_fast8_t bit_number)
{
const uint32_t bit_band_base = 0x42000000; const uint32_t bit_band_base = 0x42000000;
const uint32_t byte_offset = (uint32_t) address - 0x40000000; const uint32_t byte_offset = (uint32_t) address - 0x40000000;
const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4); const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4);
@ -29,17 +32,29 @@ volatile uint32_t* peripheral_bitband_address(volatile void* const address, cons
return (volatile uint32_t*) bit_word_address; return (volatile uint32_t*) bit_word_address;
} }
void peripheral_bitband_set(volatile void* const peripheral_address, const uint_fast8_t bit_number) { void peripheral_bitband_set(
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); volatile void* const peripheral_address,
const uint_fast8_t bit_number)
{
volatile uint32_t* const bitband_address =
peripheral_bitband_address(peripheral_address, bit_number);
*bitband_address = 1; *bitband_address = 1;
} }
void peripheral_bitband_clear(volatile void* const peripheral_address, const uint_fast8_t bit_number) { void peripheral_bitband_clear(
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); volatile void* const peripheral_address,
const uint_fast8_t bit_number)
{
volatile uint32_t* const bitband_address =
peripheral_bitband_address(peripheral_address, bit_number);
*bitband_address = 0; *bitband_address = 0;
} }
uint32_t peripheral_bitband_get(volatile void* const peripheral_address, const uint_fast8_t bit_number) { uint32_t peripheral_bitband_get(
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); volatile void* const peripheral_address,
const uint_fast8_t bit_number)
{
volatile uint32_t* const bitband_address =
peripheral_bitband_address(peripheral_address, bit_number);
return *bitband_address; return *bitband_address;
} }

View File

@ -24,9 +24,17 @@
#include <stdint.h> #include <stdint.h>
volatile uint32_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number); volatile uint32_t* peripheral_bitband_address(
void peripheral_bitband_set(volatile void* const peripheral_address, const uint_fast8_t bit_number); volatile void* const address,
void peripheral_bitband_clear(volatile void* const peripheral_address, const uint_fast8_t bit_number); const uint_fast8_t bit_number);
uint32_t peripheral_bitband_get(volatile void* const peripheral_address, const uint_fast8_t bit_number); void peripheral_bitband_set(
volatile void* const peripheral_address,
const uint_fast8_t bit_number);
void peripheral_bitband_clear(
volatile void* const peripheral_address,
const uint_fast8_t bit_number);
uint32_t peripheral_bitband_get(
volatile void* const peripheral_address,
const uint_fast8_t bit_number);
#endif //__BITBAND_H__ #endif //__BITBAND_H__

View File

@ -29,7 +29,8 @@ static refill_buffer_cb refill_buffer;
static uint32_t xsvf_buffer_len, xsvf_pos; static uint32_t xsvf_buffer_len, xsvf_pos;
static unsigned char* xsvf_buffer; static unsigned char* xsvf_buffer;
void cpld_jtag_take(jtag_t* const jtag) { void cpld_jtag_take(jtag_t* const jtag)
{
const jtag_gpio_t* const gpio = jtag->gpio; const jtag_gpio_t* const gpio = jtag->gpio;
/* Set initial GPIO state to the voltages of the internal or external pull-ups/downs, /* Set initial GPIO state to the voltages of the internal or external pull-ups/downs,
@ -53,7 +54,8 @@ void cpld_jtag_take(jtag_t* const jtag) {
gpio_input(gpio->gpio_tdo); gpio_input(gpio->gpio_tdo);
} }
void cpld_jtag_release(jtag_t* const jtag) { void cpld_jtag_release(jtag_t* const jtag)
{
const jtag_gpio_t* const gpio = jtag->gpio; const jtag_gpio_t* const gpio = jtag->gpio;
/* Make all pins inputs when JTAG interface not active. /* Make all pins inputs when JTAG interface not active.
@ -75,8 +77,8 @@ int cpld_jtag_program(
jtag_t* const jtag, jtag_t* const jtag,
const uint32_t buffer_length, const uint32_t buffer_length,
unsigned char* const buffer, unsigned char* const buffer,
refill_buffer_cb refill refill_buffer_cb refill)
) { {
int error; int error;
cpld_jtag_take(jtag); cpld_jtag_take(jtag);
xsvf_buffer = buffer; xsvf_buffer = buffer;
@ -89,7 +91,8 @@ int cpld_jtag_program(
} }
/* this gets called by the XAPP058 code */ /* this gets called by the XAPP058 code */
unsigned char cpld_jtag_get_next_byte(void) { unsigned char cpld_jtag_get_next_byte(void)
{
if (xsvf_pos == xsvf_buffer_len) { if (xsvf_pos == xsvf_buffer_len) {
refill_buffer(); refill_buffer();
xsvf_pos = 0; xsvf_pos = 0;

View File

@ -55,8 +55,7 @@ int cpld_jtag_program(
jtag_t* const jtag, jtag_t* const jtag,
const uint32_t buffer_length, const uint32_t buffer_length,
unsigned char* const buffer, unsigned char* const buffer,
refill_buffer_cb refill refill_buffer_cb refill);
);
unsigned char cpld_jtag_get_next_byte(void); unsigned char cpld_jtag_get_next_byte(void);
#endif //__CPLD_JTAG_H__ #endif //__CPLD_JTAG_H__

View File

@ -26,6 +26,7 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
// clang-format off
typedef enum { typedef enum {
CPLD_XC2C_IR_INTEST = 0b00000010, CPLD_XC2C_IR_INTEST = 0b00000010,
CPLD_XC2C_IR_BYPASS = 0b11111111, CPLD_XC2C_IR_BYPASS = 0b11111111,
@ -53,7 +54,13 @@ typedef enum {
CPLD_XC2C_IR_ISC_NOOP = 0b11100000, CPLD_XC2C_IR_ISC_NOOP = 0b11100000,
} cpld_xc2c_ir_t; } cpld_xc2c_ir_t;
static bool cpld_xc2c_jtag_clock(const jtag_t* const jtag, const uint32_t tms, const uint32_t tdi) { // clang-format on
static bool cpld_xc2c_jtag_clock(
const jtag_t* const jtag,
const uint32_t tms,
const uint32_t tdi)
{
// 8 ns TMS/TDI to TCK setup // 8 ns TMS/TDI to TCK setup
gpio_write(jtag->gpio->gpio_tdi, tdi); gpio_write(jtag->gpio->gpio_tdi, tdi);
gpio_write(jtag->gpio->gpio_tms, tms); gpio_write(jtag->gpio->gpio_tms, tms);
@ -88,27 +95,43 @@ static bool cpld_xc2c_jtag_clock(const jtag_t* const jtag, const uint32_t tms, c
return gpio_read(jtag->gpio->gpio_tdo); return gpio_read(jtag->gpio->gpio_tdo);
} }
static void cpld_xc2c_jtag_shift_ptr_tms(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t start, const size_t end, const bool tms) { static void cpld_xc2c_jtag_shift_ptr_tms(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t start,
const size_t end,
const bool tms)
{
for (size_t i = start; i < end; i++) { for (size_t i = start; i < end; i++) {
const size_t byte_n = i >> 3; const size_t byte_n = i >> 3;
const size_t bit_n = i & 7; const size_t bit_n = i & 7;
const uint32_t mask = (1U << bit_n); const uint32_t mask = (1U << bit_n);
const uint32_t tdo = cpld_xc2c_jtag_clock(jtag, tms, tdi_tdo[byte_n] & mask) ? 1 : 0; const uint32_t tdo =
cpld_xc2c_jtag_clock(jtag, tms, tdi_tdo[byte_n] & mask) ? 1 : 0;
tdi_tdo[byte_n] &= ~mask; tdi_tdo[byte_n] &= ~mask;
tdi_tdo[byte_n] |= (tdo << bit_n); tdi_tdo[byte_n] |= (tdo << bit_n);
} }
} }
static void cpld_xc2c_jtag_shift_ptr(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t count) { static void cpld_xc2c_jtag_shift_ptr(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t count)
{
if (count > 0) { if (count > 0) {
cpld_xc2c_jtag_shift_ptr_tms(jtag, tdi_tdo, 0, count - 1, false); cpld_xc2c_jtag_shift_ptr_tms(jtag, tdi_tdo, 0, count - 1, false);
cpld_xc2c_jtag_shift_ptr_tms(jtag, tdi_tdo, count - 1, count, true); cpld_xc2c_jtag_shift_ptr_tms(jtag, tdi_tdo, count - 1, count, true);
} }
} }
static uint32_t cpld_xc2c_jtag_shift_u32(const jtag_t* const jtag, const uint32_t tms, const uint32_t tdi, const size_t count) { static uint32_t cpld_xc2c_jtag_shift_u32(
const jtag_t* const jtag,
const uint32_t tms,
const uint32_t tdi,
const size_t count)
{
uint32_t tdo = 0; uint32_t tdo = 0;
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
@ -119,19 +142,26 @@ static uint32_t cpld_xc2c_jtag_shift_u32(const jtag_t* const jtag, const uint32_
return tdo; return tdo;
} }
static void cpld_xc2c_jtag_clocks(const jtag_t* const jtag, const size_t count) { static void cpld_xc2c_jtag_clocks(const jtag_t* const jtag, const size_t count)
{
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
cpld_xc2c_jtag_clock(jtag, 0, 0); cpld_xc2c_jtag_clock(jtag, 0, 0);
} }
} }
static void cpld_xc2c_jtag_pause(const jtag_t* const jtag, const size_t count) { static void cpld_xc2c_jtag_pause(const jtag_t* const jtag, const size_t count)
{
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
cpld_xc2c_jtag_clock(jtag, (i == (count - 1)), 0); cpld_xc2c_jtag_clock(jtag, (i == (count - 1)), 0);
} }
} }
static void cpld_xc2c_jtag_shift_dr_ir(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t bit_count, const size_t pause_count) { static void cpld_xc2c_jtag_shift_dr_ir(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t bit_count,
const size_t pause_count)
{
/* Run-Test/Idle or Select-DR-Scan -> Shift-DR or Shift-IR */ /* Run-Test/Idle or Select-DR-Scan -> Shift-DR or Shift-IR */
cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3); cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3);
/* Shift-[DI]R -> Exit1-[DI]R */ /* Shift-[DI]R -> Exit1-[DI]R */
@ -146,11 +176,20 @@ static void cpld_xc2c_jtag_shift_dr_ir(const jtag_t* const jtag, uint8_t* const
cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0, 2); cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0, 2);
} }
static void cpld_xc2c_jtag_shift_dr(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t bit_count, const size_t pause_count) { static void cpld_xc2c_jtag_shift_dr(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t bit_count,
const size_t pause_count)
{
cpld_xc2c_jtag_shift_dr_ir(jtag, tdi_tdo, bit_count, pause_count); cpld_xc2c_jtag_shift_dr_ir(jtag, tdi_tdo, bit_count, pause_count);
} }
static uint8_t cpld_xc2c_jtag_shift_ir_pause(const jtag_t* const jtag, const cpld_xc2c_ir_t ir, const size_t pause_count) { static uint8_t cpld_xc2c_jtag_shift_ir_pause(
const jtag_t* const jtag,
const cpld_xc2c_ir_t ir,
const size_t pause_count)
{
/* Run-Test/Idle -> Select-DR-Scan */ /* Run-Test/Idle -> Select-DR-Scan */
cpld_xc2c_jtag_shift_u32(jtag, 0b1, 0b0, 1); cpld_xc2c_jtag_shift_u32(jtag, 0b1, 0b0, 1);
uint8_t value = ir; uint8_t value = ir;
@ -158,17 +197,20 @@ static uint8_t cpld_xc2c_jtag_shift_ir_pause(const jtag_t* const jtag, const cpl
return value; return value;
} }
static uint8_t cpld_xc2c_jtag_shift_ir(const jtag_t* const jtag, const cpld_xc2c_ir_t ir) { static uint8_t cpld_xc2c_jtag_shift_ir(const jtag_t* const jtag, const cpld_xc2c_ir_t ir)
{
return cpld_xc2c_jtag_shift_ir_pause(jtag, ir, 0); return cpld_xc2c_jtag_shift_ir_pause(jtag, ir, 0);
} }
static void cpld_xc2c_jtag_reset(const jtag_t* const jtag) { static void cpld_xc2c_jtag_reset(const jtag_t* const jtag)
{
/* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram. /* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram.
*/ */
cpld_xc2c_jtag_shift_u32(jtag, 0b11111, 0, 5); cpld_xc2c_jtag_shift_u32(jtag, 0b11111, 0, 5);
} }
static void cpld_xc2c_jtag_reset_and_idle(const jtag_t* const jtag) { static void cpld_xc2c_jtag_reset_and_idle(const jtag_t* const jtag)
{
/* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram. /* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram.
* One TMS=0 to move from Test-Logic-Reset to Run-Test-Idle. * One TMS=0 to move from Test-Logic-Reset to Run-Test-Idle.
*/ */
@ -176,7 +218,8 @@ static void cpld_xc2c_jtag_reset_and_idle(const jtag_t* const jtag) {
cpld_xc2c_jtag_shift_u32(jtag, 0, 0, 1); cpld_xc2c_jtag_shift_u32(jtag, 0, 0, 1);
} }
static uint32_t cpld_xc2c_jtag_idcode(const jtag_t* const jtag) { static uint32_t cpld_xc2c_jtag_idcode(const jtag_t* const jtag)
{
/* Enter and end at Run-Test-Idle state. */ /* Enter and end at Run-Test-Idle state. */
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_IDCODE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_IDCODE);
uint32_t result = 0; uint32_t result = 0;
@ -184,34 +227,41 @@ static uint32_t cpld_xc2c_jtag_idcode(const jtag_t* const jtag) {
return result; return result;
} }
static bool cpld_xc2c64a_jtag_idcode_ok(const jtag_t* const jtag) { static bool cpld_xc2c64a_jtag_idcode_ok(const jtag_t* const jtag)
{
return ((cpld_xc2c_jtag_idcode(jtag) ^ 0xf6e5f093) & 0x0fff8fff) == 0; return ((cpld_xc2c_jtag_idcode(jtag) ^ 0xf6e5f093) & 0x0fff8fff) == 0;
} }
static void cpld_xc2c_jtag_conld(const jtag_t* const jtag) { static void cpld_xc2c_jtag_conld(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE);
cpld_xc2c_jtag_clocks(jtag, 100); cpld_xc2c_jtag_clocks(jtag, 100);
} }
static void cpld_xc2c_jtag_enable(const jtag_t* const jtag) { static void cpld_xc2c_jtag_enable(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_ENABLE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_ENABLE);
cpld_xc2c_jtag_clocks(jtag, 800); cpld_xc2c_jtag_clocks(jtag, 800);
} }
static void cpld_xc2c_jtag_disable(const jtag_t* const jtag) { static void cpld_xc2c_jtag_disable(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE);
cpld_xc2c_jtag_clocks(jtag, 100); cpld_xc2c_jtag_clocks(jtag, 100);
} }
static void cpld_xc2c_jtag_sram_write(const jtag_t* const jtag) { static void cpld_xc2c_jtag_sram_write(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_WRITE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_WRITE);
} }
static void cpld_xc2c_jtag_sram_read(const jtag_t* const jtag) { static void cpld_xc2c_jtag_sram_read(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_SRAM_READ); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_SRAM_READ);
} }
static uint32_t cpld_xc2c_jtag_bypass(const jtag_t* const jtag, const bool shift_dr) { static uint32_t cpld_xc2c_jtag_bypass(const jtag_t* const jtag, const bool shift_dr)
{
const uint8_t result = cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_BYPASS); const uint8_t result = cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_BYPASS);
if (shift_dr) { if (shift_dr) {
uint8_t dr = 0; uint8_t dr = 0;
@ -220,16 +270,19 @@ static uint32_t cpld_xc2c_jtag_bypass(const jtag_t* const jtag, const bool shift
return result; return result;
} }
static bool cpld_xc2c_jtag_read_write_protect(const jtag_t* const jtag) { static bool cpld_xc2c_jtag_read_write_protect(const jtag_t* const jtag)
{
/* Enter and end at Run-Test-Idle state. */ /* Enter and end at Run-Test-Idle state. */
return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x01) & 0x03) == 0; return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x01) & 0x03) == 0;
} }
static bool cpld_xc2c_jtag_is_done(const jtag_t* const jtag) { static bool cpld_xc2c_jtag_is_done(const jtag_t* const jtag)
{
return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x05) & 0x07) == 0; return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x05) & 0x07) == 0;
} }
static void cpld_xc2c_jtag_init_special(const jtag_t* const jtag) { static void cpld_xc2c_jtag_init_special(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_INIT); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_INIT);
cpld_xc2c_jtag_clocks(jtag, 20); cpld_xc2c_jtag_clocks(jtag, 20);
/* Run-Test/Idle -> Shift-IR */ /* Run-Test/Idle -> Shift-IR */
@ -243,11 +296,16 @@ static void cpld_xc2c_jtag_init_special(const jtag_t* const jtag) {
cpld_xc2c_jtag_clocks(jtag, 800); cpld_xc2c_jtag_clocks(jtag, 800);
} }
static void cpld_xc2c_jtag_read(const jtag_t* const jtag) { static void cpld_xc2c_jtag_read(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir_pause(jtag, CPLD_XC2C_IR_ISC_READ, 1); cpld_xc2c_jtag_shift_ir_pause(jtag, CPLD_XC2C_IR_ISC_READ, 1);
} }
static void cpld_xc2c64a_jtag_read_row(const jtag_t* const jtag, uint8_t address, uint8_t* const dr) { static void cpld_xc2c64a_jtag_read_row(
const jtag_t* const jtag,
uint8_t address,
uint8_t* const dr)
{
cpld_xc2c_jtag_shift_dr(jtag, &address, 7, 20); cpld_xc2c_jtag_shift_dr(jtag, &address, 7, 20);
cpld_xc2c_jtag_clocks(jtag, 100); cpld_xc2c_jtag_clocks(jtag, 100);
@ -262,13 +320,14 @@ static void cpld_xc2c64a_jtag_read_row(const jtag_t* const jtag, uint8_t address
bool cpld_xc2c64a_jtag_checksum( bool cpld_xc2c64a_jtag_checksum(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_verify_t* const verify, const cpld_xc2c64a_verify_t* const verify,
uint32_t* const crc_value uint32_t* const crc_value)
) { {
cpld_xc2c_jtag_reset_and_idle(jtag); cpld_xc2c_jtag_reset_and_idle(jtag);
if( cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_read_write_protect(jtag) && if (cpld_xc2c64a_jtag_idcode_ok(jtag) &&
cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_read_write_protect(jtag) ) { cpld_xc2c_jtag_read_write_protect(jtag) &&
cpld_xc2c64a_jtag_idcode_ok(jtag) &&
cpld_xc2c_jtag_read_write_protect(jtag)) {
cpld_xc2c_jtag_bypass(jtag, false); cpld_xc2c_jtag_bypass(jtag, false);
cpld_xc2c_jtag_enable(jtag); cpld_xc2c_jtag_enable(jtag);
@ -317,7 +376,11 @@ bool cpld_xc2c64a_jtag_checksum(
return false; return false;
} }
static void cpld_xc2c64a_jtag_sram_write_row(const jtag_t* const jtag, uint8_t address, const uint8_t* const data) { static void cpld_xc2c64a_jtag_sram_write_row(
const jtag_t* const jtag,
uint8_t address,
const uint8_t* const data)
{
uint8_t write[CPLD_XC2C64A_BYTES_IN_ROW]; uint8_t write[CPLD_XC2C64A_BYTES_IN_ROW];
memcpy(&write[0], data, sizeof(write)); memcpy(&write[0], data, sizeof(write));
@ -334,7 +397,11 @@ static void cpld_xc2c64a_jtag_sram_write_row(const jtag_t* const jtag, uint8_t a
cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0b00, 2); cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0b00, 2);
} }
static void cpld_xc2c64a_jtag_sram_read_row(const jtag_t* const jtag, uint8_t* const data, const uint8_t next_address) { static void cpld_xc2c64a_jtag_sram_read_row(
const jtag_t* const jtag,
uint8_t* const data,
const uint8_t next_address)
{
/* Run-Test/Idle -> Shift-DR */ /* Run-Test/Idle -> Shift-DR */
cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3); cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3);
@ -351,7 +418,12 @@ static void cpld_xc2c64a_jtag_sram_read_row(const jtag_t* const jtag, uint8_t* c
cpld_xc2c_jtag_shift_u32(jtag, 0b0110, 0b0000, 4); cpld_xc2c_jtag_shift_u32(jtag, 0b0110, 0b0000, 4);
} }
static bool cpld_xc2c64a_jtag_sram_compare_row(const jtag_t* const jtag, const uint8_t* const expected, const uint8_t* const mask, const uint8_t next_address) { static bool cpld_xc2c64a_jtag_sram_compare_row(
const jtag_t* const jtag,
const uint8_t* const expected,
const uint8_t* const mask,
const uint8_t next_address)
{
/* Run-Test/Idle -> Shift-DR */ /* Run-Test/Idle -> Shift-DR */
uint8_t read[CPLD_XC2C64A_BYTES_IN_ROW]; uint8_t read[CPLD_XC2C64A_BYTES_IN_ROW];
memset(read, 0xff, sizeof(read)); memset(read, 0xff, sizeof(read));
@ -360,7 +432,8 @@ static bool cpld_xc2c64a_jtag_sram_compare_row(const jtag_t* const jtag, const u
bool matched = true; bool matched = true;
if ((expected != NULL) && (mask != NULL)) { if ((expected != NULL) && (mask != NULL)) {
for (size_t i = 0; i < CPLD_XC2C64A_BYTES_IN_ROW; i++) { for (size_t i = 0; i < CPLD_XC2C64A_BYTES_IN_ROW; i++) {
const uint8_t significant_differences = (read[i] ^ expected[i]) & mask[i]; const uint8_t significant_differences =
(read[i] ^ expected[i]) & mask[i];
matched &= (significant_differences == 0); matched &= (significant_differences == 0);
} }
} }
@ -370,8 +443,8 @@ static bool cpld_xc2c64a_jtag_sram_compare_row(const jtag_t* const jtag, const u
void cpld_xc2c64a_jtag_sram_write( void cpld_xc2c64a_jtag_sram_write(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program const cpld_xc2c64a_program_t* const program)
) { {
cpld_xc2c_jtag_reset_and_idle(jtag); cpld_xc2c_jtag_reset_and_idle(jtag);
cpld_xc2c_jtag_enable(jtag); cpld_xc2c_jtag_enable(jtag);
@ -379,7 +452,10 @@ void cpld_xc2c64a_jtag_sram_write(
for (size_t row = 0; row < CPLD_XC2C64A_ROWS; row++) { for (size_t row = 0; row < CPLD_XC2C64A_ROWS; row++) {
const uint8_t address = cpld_hackrf_row_addresses.address[row]; const uint8_t address = cpld_hackrf_row_addresses.address[row];
cpld_xc2c64a_jtag_sram_write_row(jtag, address, &program->row[row].data[0]); cpld_xc2c64a_jtag_sram_write_row(
jtag,
address,
&program->row[row].data[0]);
} }
cpld_xc2c_jtag_disable(jtag); cpld_xc2c_jtag_disable(jtag);
@ -390,8 +466,8 @@ void cpld_xc2c64a_jtag_sram_write(
bool cpld_xc2c64a_jtag_sram_verify( bool cpld_xc2c64a_jtag_sram_verify(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program, const cpld_xc2c64a_program_t* const program,
const cpld_xc2c64a_verify_t* const verify const cpld_xc2c64a_verify_t* const verify)
) { {
cpld_xc2c_jtag_reset_and_idle(jtag); cpld_xc2c_jtag_reset_and_idle(jtag);
cpld_xc2c_jtag_enable(jtag); cpld_xc2c_jtag_enable(jtag);
@ -403,11 +479,20 @@ bool cpld_xc2c64a_jtag_sram_verify(
bool matched = true; bool matched = true;
for (size_t address_row = 0; address_row <= CPLD_XC2C64A_ROWS; address_row++) { for (size_t address_row = 0; address_row <= CPLD_XC2C64A_ROWS; address_row++) {
const int data_row = (int) address_row - 1; const int data_row = (int) address_row - 1;
const size_t mask_index = (data_row >= 0) ? verify->mask_index[data_row] : 0; const size_t mask_index =
const uint8_t* const expected = (data_row >= 0) ? &program->row[data_row].data[0] : NULL; (data_row >= 0) ? verify->mask_index[data_row] : 0;
const uint8_t* const mask = (data_row >= 0) ? &verify->mask[mask_index].value[0] : NULL; const uint8_t* const expected =
const uint8_t next_address = (address_row < CPLD_XC2C64A_ROWS) ? cpld_hackrf_row_addresses.address[address_row] : 0; (data_row >= 0) ? &program->row[data_row].data[0] : NULL;
matched &= cpld_xc2c64a_jtag_sram_compare_row(jtag, expected, mask, next_address); const uint8_t* const mask =
(data_row >= 0) ? &verify->mask[mask_index].value[0] : NULL;
const uint8_t next_address = (address_row < CPLD_XC2C64A_ROWS) ?
cpld_hackrf_row_addresses.address[address_row] :
0;
matched &= cpld_xc2c64a_jtag_sram_compare_row(
jtag,
expected,
mask,
next_address);
} }
cpld_xc2c_jtag_disable(jtag); cpld_xc2c_jtag_disable(jtag);

View File

@ -56,17 +56,14 @@ typedef struct {
bool cpld_xc2c64a_jtag_checksum( bool cpld_xc2c64a_jtag_checksum(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_verify_t* const verify, const cpld_xc2c64a_verify_t* const verify,
uint32_t* const crc_value uint32_t* const crc_value);
);
void cpld_xc2c64a_jtag_sram_write( void cpld_xc2c64a_jtag_sram_write(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program const cpld_xc2c64a_program_t* const program);
);
bool cpld_xc2c64a_jtag_sram_verify( bool cpld_xc2c64a_jtag_sram_verify(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program, const cpld_xc2c64a_program_t* const program,
const cpld_xc2c64a_verify_t* const verify const cpld_xc2c64a_verify_t* const verify);
);
extern const cpld_xc2c64a_program_t cpld_hackrf_program_sram; extern const cpld_xc2c64a_program_t cpld_hackrf_program_sram;
extern const cpld_xc2c64a_verify_t cpld_hackrf_verify; extern const cpld_xc2c64a_verify_t cpld_hackrf_verify;

View File

@ -23,13 +23,15 @@
#include <stdbool.h> #include <stdbool.h>
void crc32_init(crc32_t* const crc) { void crc32_init(crc32_t* const crc)
{
crc->remainder = 0xffffffff; crc->remainder = 0xffffffff;
crc->reversed_polynomial = 0xedb88320; crc->reversed_polynomial = 0xedb88320;
crc->final_xor = 0xffffffff; crc->final_xor = 0xffffffff;
} }
void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t byte_count) { void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t byte_count)
{
uint32_t remainder = crc->remainder; uint32_t remainder = crc->remainder;
const size_t bit_count = byte_count * 8; const size_t bit_count = byte_count * 8;
for (size_t bit_n = 0; bit_n < bit_count; bit_n++) { for (size_t bit_n = 0; bit_n < bit_count; bit_n++) {
@ -44,6 +46,7 @@ void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t by
crc->remainder = remainder; crc->remainder = remainder;
} }
uint32_t crc32_digest(const crc32_t* const crc) { uint32_t crc32_digest(const crc32_t* const crc)
{
return crc->remainder ^ crc->final_xor; return crc->remainder ^ crc->final_xor;
} }

View File

@ -24,8 +24,7 @@
#include "fault_handler.h" #include "fault_handler.h"
typedef struct typedef struct {
{
uint32_t r0; uint32_t r0;
uint32_t r1; uint32_t r1;
uint32_t r2; uint32_t r2;
@ -36,8 +35,8 @@ typedef struct
uint32_t psr; /* Program Status Register. */ uint32_t psr; /* Program Status Register. */
} hard_fault_stack_t; } hard_fault_stack_t;
__attribute__((naked)) __attribute__((naked)) void hard_fault_handler(void)
void hard_fault_handler(void) { {
__asm__("TST LR, #4"); __asm__("TST LR, #4");
__asm__("ITE EQ"); __asm__("ITE EQ");
__asm__("MRSEQ R0, MSP"); __asm__("MRSEQ R0, MSP");
@ -70,17 +69,20 @@ __attribute__((used)) void hard_fault_handler_c(uint32_t* args)
} }
} }
*/ */
while(1); while (1) {}
} }
void mem_manage_handler() { void mem_manage_handler()
while(1); {
while (1) {}
} }
void bus_fault_handler() { void bus_fault_handler()
while(1); {
while (1) {}
} }
void usage_fault_handler() { void usage_fault_handler()
while(1); {
while (1) {}
} }

View File

@ -30,6 +30,7 @@
// structures are supposedly the same between processors (to an // structures are supposedly the same between processors (to an
// undetermined extent). // undetermined extent).
typedef struct armv7m_scb_t armv7m_scb_t; typedef struct armv7m_scb_t armv7m_scb_t;
struct armv7m_scb_t { struct armv7m_scb_t {
volatile const uint32_t CPUID; volatile const uint32_t CPUID;
volatile uint32_t ICSR; volatile uint32_t ICSR;

View File

@ -23,40 +23,49 @@
#include <libopencm3/lpc43xx/gpdma.h> #include <libopencm3/lpc43xx/gpdma.h>
void gpdma_controller_enable() { void gpdma_controller_enable()
{
GPDMA_CONFIG |= GPDMA_CONFIG_E(1); GPDMA_CONFIG |= GPDMA_CONFIG_E(1);
while( (GPDMA_CONFIG & GPDMA_CONFIG_E_MASK) == 0 ); while ((GPDMA_CONFIG & GPDMA_CONFIG_E_MASK) == 0) {}
} }
void gpdma_channel_enable(const uint_fast8_t channel) { void gpdma_channel_enable(const uint_fast8_t channel)
{
GPDMA_CCONFIG(channel) |= GPDMA_CCONFIG_E(1); GPDMA_CCONFIG(channel) |= GPDMA_CCONFIG_E(1);
} }
void gpdma_channel_disable(const uint_fast8_t channel) { void gpdma_channel_disable(const uint_fast8_t channel)
{
GPDMA_CCONFIG(channel) &= ~GPDMA_CCONFIG_E_MASK; GPDMA_CCONFIG(channel) &= ~GPDMA_CCONFIG_E_MASK;
while( (GPDMA_ENBLDCHNS & GPDMA_ENBLDCHNS_ENABLEDCHANNELS(1 << channel)) ); while (GPDMA_ENBLDCHNS & GPDMA_ENBLDCHNS_ENABLEDCHANNELS(1 << channel)) {}
} }
void gpdma_channel_interrupt_tc_clear(const uint_fast8_t channel) { void gpdma_channel_interrupt_tc_clear(const uint_fast8_t channel)
{
GPDMA_INTTCCLEAR = GPDMA_INTTCCLEAR_INTTCCLEAR(1 << channel); GPDMA_INTTCCLEAR = GPDMA_INTTCCLEAR_INTTCCLEAR(1 << channel);
} }
void gpdma_channel_interrupt_error_clear(const uint_fast8_t channel) { void gpdma_channel_interrupt_error_clear(const uint_fast8_t channel)
{
GPDMA_INTERRCLR = GPDMA_INTERRCLR_INTERRCLR(1 << channel); GPDMA_INTERRCLR = GPDMA_INTERRCLR_INTERRCLR(1 << channel);
} }
void gpdma_lli_enable_interrupt(gpdma_lli_t* const lli) { void gpdma_lli_enable_interrupt(gpdma_lli_t* const lli)
{
lli->ccontrol |= GPDMA_CCONTROL_I(1); lli->ccontrol |= GPDMA_CCONTROL_I(1);
} }
void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count) { void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count)
{
for (size_t i = 0; i < lli_count; i++) { for (size_t i = 0; i < lli_count; i++) {
gpdma_lli_t* const next_lli = &lli[(i + 1) % lli_count]; gpdma_lli_t* const next_lli = &lli[(i + 1) % lli_count];
lli[i].clli = (lli[i].clli & ~GPDMA_CLLI_LLI_MASK) | GPDMA_CLLI_LLI((uint32_t)next_lli >> 2); lli[i].clli = (lli[i].clli & ~GPDMA_CLLI_LLI_MASK) |
GPDMA_CLLI_LLI((uint32_t) next_lli >> 2);
} }
} }
void gpdma_lli_create_oneshot(gpdma_lli_t* const lli, const size_t lli_count) { void gpdma_lli_create_oneshot(gpdma_lli_t* const lli, const size_t lli_count)
{
gpdma_lli_create_loop(lli, lli_count); gpdma_lli_create_loop(lli, lli_count);
lli[lli_count - 1].clli &= ~GPDMA_CLLI_LLI_MASK; lli[lli_count - 1].clli &= ~GPDMA_CLLI_LLI_MASK;
} }

View File

@ -23,36 +23,44 @@
#include <stddef.h> #include <stddef.h>
void gpio_init() { void gpio_init()
{
for (size_t i = 0; i < 8; i++) { for (size_t i = 0; i < 8; i++) {
GPIO_LPC_PORT(i)->dir = 0; GPIO_LPC_PORT(i)->dir = 0;
} }
} }
void gpio_set(gpio_t gpio) { void gpio_set(gpio_t gpio)
{
gpio->port->set = gpio->mask; gpio->port->set = gpio->mask;
} }
void gpio_clear(gpio_t gpio) { void gpio_clear(gpio_t gpio)
{
gpio->port->clr = gpio->mask; gpio->port->clr = gpio->mask;
} }
void gpio_toggle(gpio_t gpio) { void gpio_toggle(gpio_t gpio)
{
gpio->port->not = gpio->mask; gpio->port->not = gpio->mask;
} }
void gpio_output(gpio_t gpio) { void gpio_output(gpio_t gpio)
{
gpio->port->dir |= gpio->mask; gpio->port->dir |= gpio->mask;
} }
void gpio_input(gpio_t gpio) { void gpio_input(gpio_t gpio)
{
gpio->port->dir &= ~gpio->mask; gpio->port->dir &= ~gpio->mask;
} }
void gpio_write(gpio_t gpio, const bool value) { void gpio_write(gpio_t gpio, const bool value)
{
*gpio->gpio_w = value; *gpio->gpio_w = value;
} }
bool gpio_read(gpio_t gpio) { bool gpio_read(gpio_t gpio)
{
return *gpio->gpio_w; return *gpio->gpio_w;
} }

View File

@ -58,13 +58,17 @@ struct gpio_t {
#define GPIO_LPC_W_OFFSET (0x1000) #define GPIO_LPC_W_OFFSET (0x1000)
#define GPIO_LPC_PORT_OFFSET (0x2000) #define GPIO_LPC_PORT_OFFSET (0x2000)
#define GPIO_LPC_PORT(_n) ((gpio_port_t*)((GPIO_LPC_BASE + GPIO_LPC_PORT_OFFSET) + (_n) * 4)) #define GPIO_LPC_PORT(_n) \
#define GPIO_LPC_W(_port_num, _pin_num) (volatile uint32_t*)((GPIO_LPC_BASE + GPIO_LPC_W_OFFSET) + ((_port_num) * 0x80) + ((_pin_num) * 4)) ((gpio_port_t*) ((GPIO_LPC_BASE + GPIO_LPC_PORT_OFFSET) + (_n) *4))
#define GPIO_LPC_W(_port_num, _pin_num) \
(volatile uint32_t*) ((GPIO_LPC_BASE + GPIO_LPC_W_OFFSET) + ((_port_num) *0x80) + ((_pin_num) *4))
// clang-format off
#define GPIO(_port_num, _pin_num) { \ #define GPIO(_port_num, _pin_num) { \
.mask = (1UL << (_pin_num)), \ .mask = (1UL << (_pin_num)), \
.port = GPIO_LPC_PORT(_port_num), \ .port = GPIO_LPC_PORT(_port_num), \
.gpio_w = GPIO_LPC_W(_port_num, _pin_num), \ .gpio_w = GPIO_LPC_W(_port_num, _pin_num), \
} }
// clang-format on
#endif /*__GPIO_LPC_H__*/ #endif /*__GPIO_LPC_H__*/

View File

@ -56,6 +56,7 @@ static struct gpio_t gpio_led[] = {
#endif #endif
}; };
// clang-format off
static struct gpio_t gpio_1v8_enable = GPIO(3, 6); static struct gpio_t gpio_1v8_enable = GPIO(3, 6);
/* MAX2837 GPIO (XCVR_CTL) PinMux */ /* MAX2837 GPIO (XCVR_CTL) PinMux */
@ -135,6 +136,7 @@ static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8);
static struct gpio_t gpio_hw_sync_enable = GPIO(5,12); static struct gpio_t gpio_hw_sync_enable = GPIO(5,12);
static struct gpio_t gpio_rx_q_invert = GPIO(0, 13); static struct gpio_t gpio_rx_q_invert = GPIO(0, 13);
// clang-format on
i2c_bus_t i2c0 = { i2c_bus_t i2c0 = {
.obj = (void*) I2C0_BASE, .obj = (void*) I2C0_BASE,
@ -294,44 +296,45 @@ void delay(uint32_t duration)
{ {
uint32_t i; uint32_t i;
for (i = 0; i < duration; i++) for (i = 0; i < duration; i++) {
__asm__("nop"); __asm__("nop");
} }
}
void delay_us_at_mhz(uint32_t us, uint32_t mhz) void delay_us_at_mhz(uint32_t us, uint32_t mhz)
{ {
// The loop below takes 4 cycles per iteration. // The loop below takes 4 cycles per iteration.
uint32_t loop_iterations = (us * mhz) / 4; uint32_t loop_iterations = (us * mhz) / 4;
asm volatile ( asm volatile("start%=:\n"
"start%=:\n"
" subs %[ITERATIONS], #1\n" // 1 cycle " subs %[ITERATIONS], #1\n" // 1 cycle
" bpl start%=\n" // 3 cycles " bpl start%=\n" // 3 cycles
: :
: [ITERATIONS] "r" (loop_iterations) : [ITERATIONS] "r"(loop_iterations));
);
} }
/* GCD algo from wikipedia */ /* GCD algo from wikipedia */
/* http://en.wikipedia.org/wiki/Greatest_common_divisor */ /* http://en.wikipedia.org/wiki/Greatest_common_divisor */
static uint32_t static uint32_t gcd(uint32_t u, uint32_t v)
gcd(uint32_t u, uint32_t v)
{ {
int s; int s;
if (!u || !v) if (!u || !v) {
return u | v; return u | v;
}
for (s = 0; !((u | v) & 1); s++) { for (s = 0; !((u | v) & 1); s++) {
u >>= 1; u >>= 1;
v >>= 1; v >>= 1;
} }
while (!(u&1)) while (!(u & 1)) {
u >>= 1; u >>= 1;
}
do { do {
while (!(v&1)) while (!(v & 1)) {
v >>= 1; v >>= 1;
}
if (u > v) { if (u > v) {
uint32_t t; uint32_t t;
@ -341,8 +344,7 @@ gcd(uint32_t u, uint32_t v)
} }
v = v - u; v = v - u;
} } while (v);
while (v);
return u << s; return u << s;
} }
@ -393,10 +395,11 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
} }
/* Can we enable integer mode ? */ /* Can we enable integer mode ? */
if (a & 0x1 || b) if (a & 0x1 || b) {
si5351c_set_int_mode(&clock_gen, 0, 0); si5351c_set_int_mode(&clock_gen, 0, 0);
else } else {
si5351c_set_int_mode(&clock_gen, 0, 1); si5351c_set_int_mode(&clock_gen, 0, 1);
}
/* Final MS values */ /* Final MS values */
MSx_P1 = 128 * a + (128 * b / c) - 512; MSx_P1 = 128 * a + (128 * b / c) - 512;
@ -419,7 +422,8 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
return true; return true;
} }
bool sample_rate_set(const uint32_t sample_rate_hz) { bool sample_rate_set(const uint32_t sample_rate_hz)
{
uint32_t p1 = 4608; uint32_t p1 = 4608;
uint32_t p2 = 0; uint32_t p2 = 0;
uint32_t p3 = 0; uint32_t p3 = 0;
@ -482,10 +486,13 @@ bool sample_rate_set(const uint32_t sample_rate_hz) {
return true; return true;
} }
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz)
{
uint32_t bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz); uint32_t bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz);
if(bandwidth_hz_real) hackrf_ui()->set_filter_bw(bandwidth_hz_real); if (bandwidth_hz_real) {
hackrf_ui()->set_filter_bw(bandwidth_hz_real);
}
return bandwidth_hz_real != 0; return bandwidth_hz_real != 0;
} }
@ -505,8 +512,7 @@ static void cpu_clock_pll1_max_speed(void)
/* 1. Select the IRC as BASE_M4_CLK source. */ /* 1. Select the IRC as BASE_M4_CLK source. */
reg_val = CGU_BASE_M4_CLK; reg_val = CGU_BASE_M4_CLK;
reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK;
reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1);
CGU_BASE_M4_CLK_AUTOBLOCK(1);
CGU_BASE_M4_CLK = reg_val; CGU_BASE_M4_CLK = reg_val;
/* 2. Enable the crystal oscillator. */ /* 2. Enable the crystal oscillator. */
@ -521,6 +527,7 @@ static void cpu_clock_pll1_max_speed(void)
/* 5. Reconfigure PLL1 to produce the final output frequency, with the /* 5. Reconfigure PLL1 to produce the final output frequency, with the
* crystal oscillator as clock source. */ * crystal oscillator as clock source. */
reg_val = CGU_PLL1_CTRL; reg_val = CGU_PLL1_CTRL;
// clang-format off
reg_val &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK | reg_val &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK |
CGU_PLL1_CTRL_PD_MASK | CGU_PLL1_CTRL_PD_MASK |
CGU_PLL1_CTRL_FBSEL_MASK | CGU_PLL1_CTRL_FBSEL_MASK |
@ -537,10 +544,11 @@ static void cpu_clock_pll1_max_speed(void)
CGU_PLL1_CTRL_MSEL(16) | CGU_PLL1_CTRL_MSEL(16) |
CGU_PLL1_CTRL_FBSEL(0) | CGU_PLL1_CTRL_FBSEL(0) |
CGU_PLL1_CTRL_DIRECT(1); CGU_PLL1_CTRL_DIRECT(1);
// clang-format on
CGU_PLL1_CTRL = reg_val; CGU_PLL1_CTRL = reg_val;
/* 6. Wait for PLL1 to lock. */ /* 6. Wait for PLL1 to lock. */
while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)); while (!(CGU_PLL1_STAT & CGU_PLL1_STAT_LOCK_MASK)) {}
/* 7. Set the PLL1 P-divider to divide by 2 (DIRECT=0, PSEL=0). */ /* 7. Set the PLL1 P-divider to divide by 2 (DIRECT=0, PSEL=0). */
CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_DIRECT_MASK; CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_DIRECT_MASK;
@ -591,9 +599,21 @@ void cpu_clock_init(void)
*/ */
/* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */
si5351c_configure_multisynth(&clock_gen, 4, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */ si5351c_configure_multisynth(
&clock_gen,
4,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
/* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ /* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */
si5351c_configure_multisynth(&clock_gen, 5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */ si5351c_configure_multisynth(
&clock_gen,
5,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
/* MS6/CLK6 is unused. */ /* MS6/CLK6 is unused. */
/* MS7/CLK7 is unused. */ /* MS7/CLK7 is unused. */
@ -624,53 +644,51 @@ void cpu_clock_init(void)
cpu_clock_pll1_max_speed(); cpu_clock_pll1_max_speed();
/* use XTAL_OSC as clock source for APB1 */ /* use XTAL_OSC as clock source for APB1 */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1) CGU_BASE_APB1_CLK =
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL); CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL);
/* use XTAL_OSC as clock source for APB3 */ /* use XTAL_OSC as clock source for APB3 */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1) CGU_BASE_APB3_CLK =
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL); CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL);
/* use XTAL_OSC as clock source for PLL0USB */ /* use XTAL_OSC as clock source for PLL0USB */
CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_AUTOBLOCK(1) |
| CGU_PLL0USB_CTRL_AUTOBLOCK(1) CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL);
| CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL); while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {}
while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK);
/* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */
/* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */
CGU_PLL0USB_MDIV = 0x06167FFA; CGU_PLL0USB_MDIV = 0x06167FFA;
CGU_PLL0USB_NP_DIV = 0x00302062; CGU_PLL0USB_NP_DIV = 0x00302062;
CGU_PLL0USB_CTRL |= (CGU_PLL0USB_CTRL_PD(1) CGU_PLL0USB_CTRL |=
| CGU_PLL0USB_CTRL_DIRECTI(1) (CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_DIRECTI(1) |
| CGU_PLL0USB_CTRL_DIRECTO(1) CGU_PLL0USB_CTRL_DIRECTO(1) | CGU_PLL0USB_CTRL_CLKEN(1));
| CGU_PLL0USB_CTRL_CLKEN(1));
/* power on PLL0USB and wait until stable */ /* power on PLL0USB and wait until stable */
CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK; CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK;
while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)); while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {}
/* use PLL0USB as clock source for USB0 */ /* use PLL0USB as clock source for USB0 */
CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) |
| CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB);
/* Switch peripheral clock over to use PLL1 (204MHz) */ /* Switch peripheral clock over to use PLL1 (204MHz) */
CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) |
| CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB1 clock over to use PLL1 (204MHz) */ /* Switch APB1 clock over to use PLL1 (204MHz) */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1) CGU_BASE_APB1_CLK =
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB3 clock over to use PLL1 (204MHz) */ /* Switch APB3 clock over to use PLL1 (204MHz) */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1) CGU_BASE_APB3_CLK =
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_SSP0_CLK = CGU_BASE_SSP0_CLK_AUTOBLOCK(1) CGU_BASE_SSP0_CLK =
| CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_SSP0_CLK_AUTOBLOCK(1) | CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) CGU_BASE_SSP1_CLK =
| CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
#if (defined JAWBREAKER || defined HACKRF_ONE) #if (defined JAWBREAKER || defined HACKRF_ONE)
/* Disable unused clocks */ /* Disable unused clocks */
@ -771,7 +789,9 @@ clock_source_t activate_best_clock_source(void)
/* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */
} }
si5351c_set_clock_source(&clock_gen, (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); si5351c_set_clock_source(
&clock_gen,
(source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN);
hackrf_ui()->set_clock_source(source); hackrf_ui()->set_clock_source(source);
return source; return source;
} }
@ -786,7 +806,8 @@ void ssp1_set_mode_max5864(void)
spi_bus_start(max5864.bus, &ssp_config_max5864); spi_bus_start(max5864.bus, &ssp_config_max5864);
} }
void pin_setup(void) { void pin_setup(void)
{
/* Configure all GPIO as Input (safe state) */ /* Configure all GPIO as Input (safe state) */
gpio_init(); gpio_init();
@ -877,16 +898,19 @@ void pin_setup(void) {
sgpio_configure_pin_functions(&sgpio_config); sgpio_configure_pin_functions(&sgpio_config);
} }
void enable_1v8_power(void) { void enable_1v8_power(void)
{
gpio_set(&gpio_1v8_enable); gpio_set(&gpio_1v8_enable);
} }
void disable_1v8_power(void) { void disable_1v8_power(void)
{
gpio_clear(&gpio_1v8_enable); gpio_clear(&gpio_1v8_enable);
} }
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
void enable_rf_power(void) { void enable_rf_power(void)
{
uint32_t i; uint32_t i;
/* many short pulses to avoid one big voltage glitch */ /* many short pulses to avoid one big voltage glitch */
@ -897,41 +921,48 @@ void enable_rf_power(void) {
gpio_clear(&gpio_vaa_disable); gpio_clear(&gpio_vaa_disable);
} }
void disable_rf_power(void) { void disable_rf_power(void)
{
gpio_set(&gpio_vaa_disable); gpio_set(&gpio_vaa_disable);
} }
#endif #endif
#ifdef RAD1O #ifdef RAD1O
void enable_rf_power(void) { void enable_rf_power(void)
{
gpio_set(&gpio_vaa_enable); gpio_set(&gpio_vaa_enable);
} }
void disable_rf_power(void) { void disable_rf_power(void)
{
gpio_clear(&gpio_vaa_enable); gpio_clear(&gpio_vaa_enable);
} }
#endif #endif
void led_on(const led_t led) { void led_on(const led_t led)
{
gpio_set(&gpio_led[led]); gpio_set(&gpio_led[led]);
} }
void led_off(const led_t led) { void led_off(const led_t led)
{
gpio_clear(&gpio_led[led]); gpio_clear(&gpio_led[led]);
} }
void led_toggle(const led_t led) { void led_toggle(const led_t led)
{
gpio_toggle(&gpio_led[led]); gpio_toggle(&gpio_led[led]);
} }
void hw_sync_enable(const hw_sync_mode_t hw_sync_mode){ void hw_sync_enable(const hw_sync_mode_t hw_sync_mode)
{
gpio_write(&gpio_hw_sync_enable, hw_sync_mode == 1); gpio_write(&gpio_hw_sync_enable, hw_sync_mode == 1);
} }
void halt_and_flash(const uint32_t duration) { void halt_and_flash(const uint32_t duration)
/* blink LED1, LED2, and LED3 */
while (1)
{ {
/* blink LED1, LED2, and LED3 */
while (1) {
led_on(LED1); led_on(LED1);
led_on(LED2); led_on(LED2);
led_on(LED3); led_on(LED3);

View File

@ -25,8 +25,7 @@
#define __HACKRF_CORE_H #define __HACKRF_CORE_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -175,7 +174,6 @@ extern "C"
#define SCU_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */ #define SCU_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif #endif
/* SPI flash */ /* SPI flash */
#define SCU_SSP0_CIPO (P3_6) #define SCU_SSP0_CIPO (P3_6)
#define SCU_SSP0_COPI (P3_7) #define SCU_SSP0_COPI (P3_7)

View File

@ -29,6 +29,7 @@
#define UNUSED(x) (void) (x) #define UNUSED(x) (void) (x)
/* Stub functions for null UI function table */ /* Stub functions for null UI function table */
// clang-format off
void hackrf_ui_init_null(void) { } void hackrf_ui_init_null(void) { }
void hackrf_ui_deinit_null(void) { } void hackrf_ui_deinit_null(void) { }
void hackrf_ui_set_frequency_null(uint64_t frequency) { UNUSED(frequency); } void hackrf_ui_set_frequency_null(uint64_t frequency) { UNUSED(frequency); }
@ -46,6 +47,8 @@ void hackrf_ui_set_clock_source_null(clock_source_t source) { UNUSED(source); }
void hackrf_ui_set_transceiver_mode_null(transceiver_mode_t mode) { UNUSED(mode); } void hackrf_ui_set_transceiver_mode_null(transceiver_mode_t mode) { UNUSED(mode); }
bool hackrf_ui_operacake_gpio_compatible_null(void) { return true; } bool hackrf_ui_operacake_gpio_compatible_null(void) { return true; }
// clang-format on
/* Null UI function table, used if there's no hardware UI detected. Eliminates the /* Null UI function table, used if there's no hardware UI detected. Eliminates the
* need to check for null UI before calling a function in the table. * need to check for null UI before calling a function in the table.
*/ */
@ -65,13 +68,13 @@ static const hackrf_ui_t hackrf_ui_null = {
&hackrf_ui_set_antenna_bias_null, &hackrf_ui_set_antenna_bias_null,
&hackrf_ui_set_clock_source_null, &hackrf_ui_set_clock_source_null,
&hackrf_ui_set_transceiver_mode_null, &hackrf_ui_set_transceiver_mode_null,
&hackrf_ui_operacake_gpio_compatible_null &hackrf_ui_operacake_gpio_compatible_null};
};
static const hackrf_ui_t* ui = NULL; static const hackrf_ui_t* ui = NULL;
static bool ui_enabled = true; static bool ui_enabled = true;
const hackrf_ui_t* hackrf_ui(void) { const hackrf_ui_t* hackrf_ui(void)
{
/* Detect on first use. If no UI hardware is detected, use a stub function table. */ /* Detect on first use. If no UI hardware is detected, use a stub function table. */
if (ui == NULL && ui_enabled) { if (ui == NULL && ui_enabled) {
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
@ -92,7 +95,8 @@ const hackrf_ui_t* hackrf_ui(void) {
return ui; return ui;
} }
void hackrf_ui_set_enable(bool enabled) { void hackrf_ui_set_enable(bool enabled)
{
if (ui_enabled != enabled) { if (ui_enabled != enabled) {
ui_enabled = enabled; ui_enabled = enabled;
hackrf_ui()->deinit(); hackrf_ui()->deinit();

View File

@ -21,19 +21,23 @@
#include "i2c_bus.h" #include "i2c_bus.h"
void i2c_bus_start(i2c_bus_t* const bus, const void* const config) { void i2c_bus_start(i2c_bus_t* const bus, const void* const config)
{
bus->start(bus, config); bus->start(bus, config);
} }
void i2c_bus_stop(i2c_bus_t* const bus) { void i2c_bus_stop(i2c_bus_t* const bus)
{
bus->stop(bus); bus->stop(bus);
} }
void i2c_bus_transfer( void i2c_bus_transfer(
i2c_bus_t* const bus, i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const tx, const size_t tx_count, const uint8_t* const tx,
uint8_t* const rx, const size_t rx_count const size_t tx_count,
) { uint8_t* const rx,
const size_t rx_count)
{
bus->transfer(bus, peripheral_address, tx, tx_count, rx, rx_count); bus->transfer(bus, peripheral_address, tx, tx_count, rx, rx_count);
} }

View File

@ -35,9 +35,10 @@ struct i2c_bus_t {
void (*transfer)( void (*transfer)(
i2c_bus_t* const bus, i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const tx, const size_t tx_count, const uint8_t* const tx,
uint8_t* const rx, const size_t rx_count const size_t tx_count,
); uint8_t* const rx,
const size_t rx_count);
}; };
void i2c_bus_start(i2c_bus_t* const bus, const void* const config); void i2c_bus_start(i2c_bus_t* const bus, const void* const config);
@ -45,8 +46,9 @@ void i2c_bus_stop(i2c_bus_t* const bus);
void i2c_bus_transfer( void i2c_bus_transfer(
i2c_bus_t* const bus, i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const tx, const size_t tx_count, const uint8_t* const tx,
uint8_t* const rx, const size_t rx_count const size_t tx_count,
); uint8_t* const rx,
const size_t rx_count);
#endif /*__I2C_BUS_H__*/ #endif /*__I2C_BUS_H__*/

View File

@ -26,23 +26,28 @@
/* FIXME return i2c0 status from each function */ /* FIXME return i2c0 status from each function */
void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config) { void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config)
{
const i2c_lpc_config_t* const config = _config; const i2c_lpc_config_t* const config = _config;
const uint32_t port = (uint32_t) bus->obj; const uint32_t port = (uint32_t) bus->obj;
i2c_init(port, config->duty_cycle_count); i2c_init(port, config->duty_cycle_count);
} }
void i2c_lpc_stop(i2c_bus_t* const bus) { void i2c_lpc_stop(i2c_bus_t* const bus)
{
const uint32_t port = (uint32_t) bus->obj; const uint32_t port = (uint32_t) bus->obj;
i2c_disable(port); i2c_disable(port);
} }
void i2c_lpc_transfer(i2c_bus_t* const bus, void i2c_lpc_transfer(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const data_tx, const size_t count_tx, const uint8_t* const data_tx,
uint8_t* const data_rx, const size_t count_rx const size_t count_tx,
) { uint8_t* const data_rx,
const size_t count_rx)
{
const uint32_t port = (uint32_t) bus->obj; const uint32_t port = (uint32_t) bus->obj;
size_t i; size_t i;
bool ack = false; bool ack = false;
@ -67,7 +72,8 @@ void i2c_lpc_transfer(i2c_bus_t* const bus,
i2c_stop(port); i2c_stop(port);
} }
bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address) { bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address)
{
const uint32_t port = (uint32_t) bus->obj; const uint32_t port = (uint32_t) bus->obj;
i2c_tx_start(port); i2c_tx_start(port);

View File

@ -34,11 +34,13 @@ typedef struct i2c_lpc_config_t {
void i2c_lpc_start(i2c_bus_t* const bus, const void* const config); void i2c_lpc_start(i2c_bus_t* const bus, const void* const config);
void i2c_lpc_stop(i2c_bus_t* const bus); void i2c_lpc_stop(i2c_bus_t* const bus);
void i2c_lpc_transfer(i2c_bus_t* const bus, void i2c_lpc_transfer(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const data_tx, const size_t count_tx, const uint8_t* const data_tx,
uint8_t* const data_rx, const size_t count_rx const size_t count_tx,
); uint8_t* const data_rx,
const size_t count_rx);
bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address); bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address);
#endif /*__I2C_LPC_H__*/ #endif /*__I2C_LPC_H__*/

View File

@ -19,8 +19,7 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
int main() { int main()
while(1) { {
while (1) {}
}
} }

View File

@ -119,13 +119,15 @@ void max2837_setup(max2837_driver_t* const drv)
max2837_regs_commit(drv); max2837_regs_commit(drv);
} }
static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r)
{
uint16_t value = (1 << 15) | (r << 10); uint16_t value = (1 << 15) | (r << 10);
spi_bus_transfer(drv->bus, &value, 1); spi_bus_transfer(drv->bus, &value, 1);
return value & 0x3ff; return value & 0x3ff;
} }
static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v)
{
uint16_t value = (r << 10) | (v & 0x3ff); uint16_t value = (r << 10) | (v & 0x3ff);
spi_bus_transfer(drv->bus, &value, 1); spi_bus_transfer(drv->bus, &value, 1);
} }
@ -160,11 +162,13 @@ void max2837_regs_commit(max2837_driver_t* const drv)
} }
} }
void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { void max2837_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode)
{
drv->set_mode(drv, new_mode); drv->set_mode(drv, new_mode);
} }
max2837_mode_t max2837_mode(max2837_driver_t* const drv) { max2837_mode_t max2837_mode(max2837_driver_t* const drv)
{
return drv->mode; return drv->mode;
} }
@ -210,16 +214,13 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq)
if (freq < 2400000000U) { if (freq < 2400000000U) {
band = MAX2837_LOGEN_BSW_2_3; band = MAX2837_LOGEN_BSW_2_3;
lna_band = MAX2837_LNAband_2_4; lna_band = MAX2837_LNAband_2_4;
} } else if (freq < 2500000000U) {
else if (freq < 2500000000U) {
band = MAX2837_LOGEN_BSW_2_4; band = MAX2837_LOGEN_BSW_2_4;
lna_band = MAX2837_LNAband_2_4; lna_band = MAX2837_LNAband_2_4;
} } else if (freq < 2600000000U) {
else if (freq < 2600000000U) {
band = MAX2837_LOGEN_BSW_2_5; band = MAX2837_LOGEN_BSW_2_5;
lna_band = MAX2837_LNAband_2_6; lna_band = MAX2837_LNAband_2_6;
} } else {
else {
band = MAX2837_LOGEN_BSW_2_6; band = MAX2837_LOGEN_BSW_2_6;
lna_band = MAX2837_LNAband_2_6; lna_band = MAX2837_LNAband_2_6;
} }
@ -259,6 +260,7 @@ typedef struct {
uint32_t ft; uint32_t ft;
} max2837_ft_t; } max2837_ft_t;
// clang-format off
static const max2837_ft_t max2837_ft[] = { static const max2837_ft_t max2837_ft[] = {
{ 1750000, MAX2837_FT_1_75M }, { 1750000, MAX2837_FT_1_75M },
{ 2500000, MAX2837_FT_2_5M }, { 2500000, MAX2837_FT_2_5M },
@ -278,6 +280,7 @@ static const max2837_ft_t max2837_ft[] = {
{ 28000000, MAX2837_FT_28M }, { 28000000, MAX2837_FT_28M },
{ 0, 0 }, { 0, 0 },
}; };
//clang-format on
uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz) { uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz) {
const max2837_ft_t* p = max2837_ft; const max2837_ft_t* p = max2837_ft;
@ -326,8 +329,9 @@ bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db) {
} }
bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db) { bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db) {
if( (gain_db & 0x1) || gain_db > 62)/* 0b11111*2 */ if( (gain_db & 0x1) || gain_db > 62) {/* 0b11111*2 */
return false; return false;
}
set_MAX2837_VGA(drv, 31-(gain_db >> 1) ); set_MAX2837_VGA(drv, 31-(gain_db >> 1) );
max2837_reg_commit(drv, 5); max2837_reg_commit(drv, 5);

View File

@ -81,7 +81,9 @@ extern void max2837_stop(max2837_driver_t* const drv);
/* Set frequency in Hz. Frequency setting is a multi-step function /* Set frequency in Hz. Frequency setting is a multi-step function
* where order of register writes matters. */ * where order of register writes matters. */
extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq); extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq);
uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz); uint32_t max2837_set_lpf_bandwidth(
max2837_driver_t* const drv,
const uint32_t bandwidth_hz);
bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db); bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db);
bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db); bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db);
bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db); bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db);

View File

@ -25,7 +25,8 @@
#include <libopencm3/lpc43xx/scu.h> #include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h" #include "hackrf_core.h"
void max2837_target_init(max2837_driver_t* const drv) { void max2837_target_init(max2837_driver_t* const drv)
{
/* Configure SSP1 Peripheral (to be moved later in SSP driver) */ /* Configure SSP1 Peripheral (to be moved later in SSP driver) */
scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
@ -44,7 +45,8 @@ void max2837_target_init(max2837_driver_t* const drv) {
gpio_output(drv->gpio_tx_enable); gpio_output(drv->gpio_tx_enable);
} }
void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode)
{
/* MAX2837_MODE_SHUTDOWN: /* MAX2837_MODE_SHUTDOWN:
* All circuit blocks are powered down, except the 4-wire serial bus * All circuit blocks are powered down, except the 4-wire serial bus
* and its internal programmable registers. * and its internal programmable registers.

View File

@ -115,7 +115,6 @@ static void delay_ms(int ms)
} }
} }
static void serial_delay(void) static void serial_delay(void)
{ {
uint32_t i; uint32_t i;
@ -124,13 +123,13 @@ static void serial_delay(void)
__asm__("nop"); __asm__("nop");
} }
/* SPI register write /* SPI register write
* *
* Send 32 bits: * Send 32 bits:
* First 29 bits are data * First 29 bits are data
* Last 3 bits are register number */ * Last 3 bits are register number */
static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v) { static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v)
{
#if DEBUG #if DEBUG
LOG("0x%04x -> reg%d\n", v, r); LOG("0x%04x -> reg%d\n", v, r);
#else #else
@ -217,7 +216,7 @@ uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz)
max2871_set_DIVA(diva); max2871_set_DIVA(diva);
max2871_write_registers(drv); max2871_write_registers(drv);
while(max2871_spi_read(drv) & MAX2871_VASA); while (max2871_spi_read(drv) & MAX2871_VASA) {}
max2871_set_RFA_EN(1); max2871_set_RFA_EN(1);
max2871_write_registers(drv); max2871_write_registers(drv);
@ -229,8 +228,8 @@ void max2871_enable(max2871_driver_t* const drv)
{ {
gpio_set(drv->gpio_vco_ce); gpio_set(drv->gpio_vco_ce);
} }
void max2871_disable(max2871_driver_t* const drv) void max2871_disable(max2871_driver_t* const drv)
{ {
gpio_clear(drv->gpio_vco_ce); gpio_clear(drv->gpio_vco_ce);
} }

View File

@ -23,15 +23,18 @@
#include "max5864.h" #include "max5864.h"
static void max5864_write(max5864_driver_t* const drv, uint8_t value) { static void max5864_write(max5864_driver_t* const drv, uint8_t value)
{
spi_bus_transfer(drv->bus, &value, 1); spi_bus_transfer(drv->bus, &value, 1);
} }
static void max5864_init(max5864_driver_t* const drv) { static void max5864_init(max5864_driver_t* const drv)
{
drv->target_init(drv); drv->target_init(drv);
} }
void max5864_setup(max5864_driver_t* const drv) { void max5864_setup(max5864_driver_t* const drv)
{
max5864_init(drv); max5864_init(drv);
} }

View File

@ -24,7 +24,8 @@
#include <libopencm3/lpc43xx/scu.h> #include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h" #include "hackrf_core.h"
void max5864_target_init(max5864_driver_t* const drv) { void max5864_target_init(max5864_driver_t* const drv)
{
(void) drv; (void) drv;
/* Configure SSP1 Peripheral (to be moved later in SSP driver) */ /* Configure SSP1 Peripheral (to be moved later in SSP driver) */

View File

@ -5,6 +5,7 @@
#include "gpio_lpc.h" #include "gpio_lpc.h"
/* RFFC5071 GPIO serial interface PinMux */ /* RFFC5071 GPIO serial interface PinMux */
// clang-format off
#if (defined JAWBREAKER || defined HACKRF_ONE) #if (defined JAWBREAKER || defined HACKRF_ONE)
static struct gpio_t gpio_rffc5072_select = GPIO(2, 13); static struct gpio_t gpio_rffc5072_select = GPIO(2, 13);
static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6); static struct gpio_t gpio_rffc5072_clock = GPIO(5, 6);
@ -19,6 +20,7 @@ static struct gpio_t gpio_vco_le = GPIO(2, 14);
static struct gpio_t gpio_vco_mux = GPIO(5, 25); static struct gpio_t gpio_vco_mux = GPIO(5, 25);
static struct gpio_t gpio_synt_rfout_en = GPIO(3, 5); static struct gpio_t gpio_synt_rfout_en = GPIO(3, 5);
#endif #endif
// clang-format on
#if (defined JAWBREAKER || defined HACKRF_ONE) #if (defined JAWBREAKER || defined HACKRF_ONE)
const rffc5071_spi_config_t rffc5071_spi_config = { const rffc5071_spi_config_t rffc5071_spi_config = {

View File

@ -60,9 +60,9 @@
#define OPERACAKE_REG_POLARITY 0x02 #define OPERACAKE_REG_POLARITY 0x02
#define OPERACAKE_REG_CONFIG 0x03 #define OPERACAKE_REG_CONFIG 0x03
#define OPERACAKE_DEFAULT_OUTPUT (OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE \ #define OPERACAKE_DEFAULT_OUTPUT \
| OPERACAKE_PORT_A1 | OPERACAKE_PORT_B1 \ (OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE | OPERACAKE_PORT_A1 | \
| OPERACAKE_EN_LEDS) OPERACAKE_PORT_B1 | OPERACAKE_EN_LEDS)
#define OPERACAKE_CONFIG_ALL_OUTPUT (0x00) #define OPERACAKE_CONFIG_ALL_OUTPUT (0x00)
// Leave LED bits as outputs // Leave LED bits as outputs
#define OPERACAKE_CONFIG_GPIO_INPUTS (0x7C) #define OPERACAKE_CONFIG_GPIO_INPUTS (0x7C)
@ -96,7 +96,8 @@ struct operacake_state operacake_boards[OPERACAKE_MAX_BOARDS];
bool allow_gpio_mode = true; bool allow_gpio_mode = true;
/* read single register */ /* read single register */
uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg) { uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg)
{
// Convert from Opera Cake address (0-7) to I2C address // Convert from Opera Cake address (0-7) to I2C address
address += OPERACAKE_ADDRESS_DEFAULT; address += OPERACAKE_ADDRESS_DEFAULT;
@ -107,7 +108,8 @@ uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg) {
} }
/* Write to one of the PCA9557 registers */ /* Write to one of the PCA9557 registers */
void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uint8_t value) { void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uint8_t value)
{
// Convert from Opera Cake address (0-7) to I2C address // Convert from Opera Cake address (0-7) to I2C address
address += OPERACAKE_ADDRESS_DEFAULT; address += OPERACAKE_ADDRESS_DEFAULT;
@ -115,12 +117,19 @@ void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uin
i2c_bus_transfer(bus, address, data, 2, NULL, 0); i2c_bus_transfer(bus, address, data, 2, NULL, 0);
} }
uint8_t operacake_init(bool allow_gpio) { uint8_t operacake_init(bool allow_gpio)
{
/* Find connected operacakes */ /* Find connected operacakes */
for (int addr = 0; addr < 8; addr++) { for (int addr = 0; addr < 8; addr++) {
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_OUTPUT, operacake_write_reg(
oc_bus,
addr,
OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT); OPERACAKE_DEFAULT_OUTPUT);
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_CONFIG, operacake_write_reg(
oc_bus,
addr,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT); OPERACAKE_CONFIG_ALL_OUTPUT);
uint8_t reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG); uint8_t reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG);
@ -136,25 +145,30 @@ uint8_t operacake_init(bool allow_gpio) {
return 0; return 0;
} }
bool operacake_is_board_present(uint8_t address) { bool operacake_is_board_present(uint8_t address)
if (address >= OPERACAKE_MAX_BOARDS) {
if (address >= OPERACAKE_MAX_BOARDS) {
return false; return false;
}
return operacake_boards[address].present; return operacake_boards[address].present;
} }
void operacake_get_boards(uint8_t *addresses) { void operacake_get_boards(uint8_t* addresses)
{
int count = 0; int count = 0;
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) { for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
addresses[i] = OPERACAKE_ADDRESS_INVALID; addresses[i] = OPERACAKE_ADDRESS_INVALID;
} }
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) { for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
if (operacake_is_board_present(i)) if (operacake_is_board_present(i)) {
addresses[count++] = i; addresses[count++] = i;
} }
} }
}
uint8_t port_to_pins(uint8_t port) { uint8_t port_to_pins(uint8_t port)
{
switch (port) { switch (port) {
case OPERACAKE_PA1: case OPERACAKE_PA1:
return OPERACAKE_PORT_A1; return OPERACAKE_PORT_A1;
@ -188,8 +202,8 @@ uint8_t operacake_activate_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 1; return 1;
} }
/* Ensure PA and PB are on opposite sides. */ /* Ensure PA and PB are on opposite sides. */
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) ||
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) { ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
return 1; return 1;
} }
@ -207,35 +221,53 @@ uint8_t operacake_activate_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 0; return 0;
} }
void operacake_set_mode(uint8_t address, uint8_t mode) { void operacake_set_mode(uint8_t address, uint8_t mode)
if (address >= OPERACAKE_MAX_BOARDS) {
if (address >= OPERACAKE_MAX_BOARDS) {
return; return;
}
operacake_boards[address].mode = mode; operacake_boards[address].mode = mode;
current_range = INVALID_RANGE; current_range = INVALID_RANGE;
if (mode == MODE_TIME) { if (mode == MODE_TIME) {
// Switch Opera Cake to pin-control mode // Switch Opera Cake to pin-control mode
uint8_t config_pins = (uint8_t)~(OPERACAKE_PIN_OE(1) | OPERACAKE_PIN_LEDEN(1) | OPERACAKE_PIN_LEDEN2(1)); uint8_t config_pins = (uint8_t) ~(
OPERACAKE_PIN_OE(1) | OPERACAKE_PIN_LEDEN(1) |
OPERACAKE_PIN_LEDEN2(1));
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, config_pins); operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, config_pins);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS); operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_OUTPUT,
OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS);
} else { } else {
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, OPERACAKE_CONFIG_ALL_OUTPUT); operacake_write_reg(
operacake_activate_ports(address, operacake_boards[address].PA, operacake_boards[address].PB); oc_bus,
address,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_activate_ports(
address,
operacake_boards[address].PA,
operacake_boards[address].PB);
} }
// If any boards are in MODE_TIME, enable the sctimer events. // If any boards are in MODE_TIME, enable the sctimer events.
bool enable_sctimer = false; bool enable_sctimer = false;
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) { for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
if (operacake_boards[i].mode == MODE_TIME) if (operacake_boards[i].mode == MODE_TIME) {
enable_sctimer = true; enable_sctimer = true;
} }
}
operacake_sctimer_enable(enable_sctimer); operacake_sctimer_enable(enable_sctimer);
} }
uint8_t operacake_get_mode(uint8_t address) { uint8_t operacake_get_mode(uint8_t address)
if (address >= OPERACAKE_MAX_BOARDS) {
if (address >= OPERACAKE_MAX_BOARDS) {
return 0; return 0;
}
return operacake_boards[address].mode; return operacake_boards[address].mode;
} }
@ -250,8 +282,8 @@ uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 1; return 1;
} }
/* Ensure PA and PB are on opposite sides. */ /* Ensure PA and PB are on opposite sides. */
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) ||
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) { ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
return 1; return 1;
} }
@ -280,7 +312,8 @@ typedef struct {
static operacake_range ranges[MAX_OPERACAKE_RANGES * sizeof(operacake_range)]; static operacake_range ranges[MAX_OPERACAKE_RANGES * sizeof(operacake_range)];
static uint8_t range_idx = 0; static uint8_t range_idx = 0;
uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port) { uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port)
{
if (range_idx >= MAX_OPERACAKE_RANGES) { if (range_idx >= MAX_OPERACAKE_RANGES) {
return 1; return 1;
} }
@ -301,15 +334,16 @@ void operacake_clear_ranges(void)
#define FREQ_ONE_MHZ (1000000ull) #define FREQ_ONE_MHZ (1000000ull)
uint8_t operacake_set_range(uint32_t freq_mhz) { uint8_t operacake_set_range(uint32_t freq_mhz)
{
if (range_idx == 0) { if (range_idx == 0) {
return 1; return 1;
} }
int range; int range;
for (range = 0; range < range_idx; range++) { for (range = 0; range < range_idx; range++) {
if((freq_mhz >= ranges[range].freq_min) if ((freq_mhz >= ranges[range].freq_min) &&
&& (freq_mhz <= ranges[range].freq_max)) { (freq_mhz <= ranges[range].freq_max)) {
break; break;
} }
} }
@ -322,8 +356,12 @@ uint8_t operacake_set_range(uint32_t freq_mhz) {
} }
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) { for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
if (operacake_is_board_present(i) && operacake_get_mode(i) == MODE_FREQUENCY) { if (operacake_is_board_present(i) &&
operacake_activate_ports(i, ranges[range].portA, ranges[range].portB); operacake_get_mode(i) == MODE_FREQUENCY) {
operacake_activate_ports(
i,
ranges[range].portA,
ranges[range].portB);
break; break;
} }
} }
@ -339,8 +377,9 @@ uint16_t gpio_test(uint8_t address)
{ {
uint8_t i, reg, bit_mask, gpio_mask = 0x1F; uint8_t i, reg, bit_mask, gpio_mask = 0x1F;
uint16_t result = 0; uint16_t result = 0;
if(!allow_gpio_mode) if (!allow_gpio_mode) {
return 0xFFFF; return 0xFFFF;
}
scu_pinmux(SCU_PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_GPIO3_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_GPIO3_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -358,9 +397,15 @@ uint16_t gpio_test(uint8_t address)
// Setup I2C to put it in GPIO mode // Setup I2C to put it in GPIO mode
reg = (OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS); reg = (OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, reg); operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, reg);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_GPIO_INPUTS); OPERACAKE_CONFIG_GPIO_INPUTS);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_POLARITY, operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_POLARITY,
OPERACAKE_POLARITY_NORMAL); OPERACAKE_POLARITY_NORMAL);
// clear state // clear state
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++) {
@ -406,9 +451,15 @@ uint16_t gpio_test(uint8_t address)
} }
// Put it back in to I2C mode and set default pins // Put it back in to I2C mode and set default pins
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT); OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT); OPERACAKE_DEFAULT_OUTPUT);
return result; return result;
} }

View File

@ -23,8 +23,7 @@
#define __OPERACAKE_H #define __OPERACAKE_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <stdint.h> #include <stdint.h>

View File

@ -30,7 +30,6 @@
#include <libopencm3/lpc43xx/gima.h> #include <libopencm3/lpc43xx/gima.h>
#include "sct.h" #include "sct.h"
#define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_SET SCT_OUT14_SET
#define U1CTRL_CLR SCT_OUT14_CLR #define U1CTRL_CLR SCT_OUT14_CLR
#define U2CTRL0_SET SCT_OUT13_SET #define U2CTRL0_SET SCT_OUT13_SET
@ -53,7 +52,8 @@ static uint32_t default_output = 0;
* To trigger the antenna switching synchronously with the sample clock, the * To trigger the antenna switching synchronously with the sample clock, the
* SGPIO is configured to output its clock (f=2 * sample clock) to the SCTimer. * SGPIO is configured to output its clock (f=2 * sample clock) to the SCTimer.
*/ */
void operacake_sctimer_init() { void operacake_sctimer_init()
{
// We start by resetting the SCTimer // We start by resetting the SCTimer
RESET_CTRL1 = RESET_CTRL1_SCT_RST; RESET_CTRL1 = RESET_CTRL1_SCT_RST;
@ -67,23 +67,30 @@ void operacake_sctimer_init() {
// this delay may need to be increased. // this delay may need to be increased.
delay(8); delay(8);
// Pin definitions for the HackRF // Pin definitions for the HackRF
// U2CTRL0 // U2CTRL0
scu_pinmux(P7_4, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_4,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U2CTRL1 // U2CTRL1
scu_pinmux(P7_5, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_5,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U3CTRL0 // U3CTRL0
scu_pinmux(P7_6, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_6,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U3CTRL1 // U3CTRL1
scu_pinmux(P7_7, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_7,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U1CTRL // U1CTRL
scu_pinmux(P7_0, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_0,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12 // Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12
SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode
SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode
SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe
SGPIO_GPIO_OENREG |= BIT12; SGPIO_GPIO_OENREG |= BIT12;
@ -91,9 +98,8 @@ void operacake_sctimer_init() {
GIMA_CTIN_1_IN = 0x2 << 4; // Route SGPIO12 to SCTIN1 GIMA_CTIN_1_IN = 0x2 << 4; // Route SGPIO12 to SCTIN1
// We configure this register first, because the user manual says to // We configure this register first, because the user manual says to
SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT | SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK |
| SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1;
| SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1;
// Halt the SCTimer to enable it to be configured // Halt the SCTimer to enable it to be configured
SCT_CTRL = SCT_CTRL_HALT_L(1); SCT_CTRL = SCT_CTRL_HALT_L(1);
@ -108,28 +114,30 @@ void operacake_sctimer_init() {
SCT_CTRL &= ~SCT_CTRL_HALT_L(1); SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
} }
static uint32_t operacake_sctimer_port_to_output(uint8_t port) { static uint32_t operacake_sctimer_port_to_output(uint8_t port)
{
int bit0 = (port >> 0) & 1; int bit0 = (port >> 0) & 1;
int bit1 = (port >> 1) & 1; int bit1 = (port >> 1) & 1;
int bit2 = (port >> 2) & 1; int bit2 = (port >> 2) & 1;
return (bit0 << 11) | (bit0 << 13) | return (bit0 << 11) | (bit0 << 13) | (bit1 << 8) | (bit1 << 12) |
(bit1 << 8) | (bit1 << 12) |
(((~bit2) & 1) << 14); (((~bit2) & 1) << 14);
} }
void operacake_sctimer_enable(bool enable) { void operacake_sctimer_enable(bool enable)
{
SCT_CTRL = SCT_CTRL_HALT_L(1); SCT_CTRL = SCT_CTRL_HALT_L(1);
SCT_STATE = enable; SCT_STATE = enable;
SCT_CTRL &= ~SCT_CTRL_HALT_L(1); SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
} }
void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int n) { void operacake_sctimer_set_dwell_times(struct operacake_dwell_times* times, int n)
{
SCT_CTRL = SCT_CTRL_HALT_L(1); SCT_CTRL = SCT_CTRL_HALT_L(1);
uint32_t counter = 0; uint32_t counter = 0;
uint32_t bit0_set = 0, bit0_clr = 0, bit1_set = 0, bit1_clr = 0, bit2_set = 0, bit2_clr = 0; uint32_t bit0_set = 0, bit0_clr = 0, bit1_set = 0, bit1_clr = 0, bit2_set = 0,
bit2_clr = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
// Enable event i in state 1, set to match on match register i // Enable event i in state 1, set to match on match register i
SCT_EVn_STATE(i) = SCT_EVn_STATE_STATEMSK1(1); SCT_EVn_STATE(i) = SCT_EVn_STATE_STATEMSK1(1);
@ -140,8 +148,9 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
// Wrapping from SCT_LIMIT seems to add an extra cycle, // Wrapping from SCT_LIMIT seems to add an extra cycle,
// so we reduce the counter value for the first event. // so we reduce the counter value for the first event.
if (i == 0) if (i == 0) {
counter -= 1; counter -= 1;
}
SCT_MATCHn(i) = counter; SCT_MATCHn(i) = counter;
SCT_MATCHRELn(i) = counter; SCT_MATCHRELn(i) = counter;
@ -192,7 +201,8 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
SCT_CTRL &= ~SCT_CTRL_HALT_L(1); SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
} }
void operacake_sctimer_stop() { void operacake_sctimer_stop()
{
// Halt timer // Halt timer
SCT_CTRL |= SCT_CTRL_HALT_L(1); SCT_CTRL |= SCT_CTRL_HALT_L(1);
} }
@ -203,7 +213,8 @@ void operacake_sctimer_stop() {
* called by set_transceiver_mode so the HackRF starts capturing with the * called by set_transceiver_mode so the HackRF starts capturing with the
* same antenna selected each time. * same antenna selected each time.
*/ */
void operacake_sctimer_reset_state() { void operacake_sctimer_reset_state()
{
SCT_CTRL |= SCT_CTRL_HALT_L(1); SCT_CTRL |= SCT_CTRL_HALT_L(1);
// Clear the counter value // Clear the counter value

View File

@ -26,19 +26,25 @@
#include <libopencm3/lpc43xx/scu.h> #include <libopencm3/lpc43xx/scu.h>
static void portapack_sleep_milliseconds(const uint32_t milliseconds) { static void portapack_sleep_milliseconds(const uint32_t milliseconds)
{
/* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */
delay(milliseconds * 40800); delay(milliseconds * 40800);
} }
// clang-format off
static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */ static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */
static struct gpio_t gpio_addr = GPIO(5, 1); /* P2_1 */ static struct gpio_t gpio_addr = GPIO(5, 1); /* P2_1 */
__attribute__((unused)) static struct gpio_t gpio_lcd_te = GPIO(5, 3); /* P2_3 */ __attribute__((unused))
__attribute__((unused)) static struct gpio_t gpio_unused = GPIO(5, 7); /* P2_8 */ static struct gpio_t gpio_lcd_te = GPIO(5, 3); /* P2_3 */
__attribute__((unused))
static struct gpio_t gpio_unused = GPIO(5, 7); /* P2_8 */
static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */ static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */
static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */ static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */
static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */ static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */
// clang-format on
typedef struct portapack_if_t { typedef struct portapack_if_t {
gpio_t gpio_dir; gpio_t gpio_dir;
gpio_t gpio_lcd_rdx; gpio_t gpio_lcd_rdx;
@ -63,26 +69,31 @@ static portapack_if_t portapack_if = {
#define GPIO_DATA_SHIFT (8) #define GPIO_DATA_SHIFT (8)
static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT; static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT;
static void portapack_data_mask_set() { static void portapack_data_mask_set()
{
portapack_if.gpio_port_data->mask = ~gpio_data_mask; portapack_if.gpio_port_data->mask = ~gpio_data_mask;
} }
static void portapack_data_write_low(const uint32_t value) { static void portapack_data_write_low(const uint32_t value)
{
portapack_if.gpio_port_data->mpin = (value << GPIO_DATA_SHIFT); portapack_if.gpio_port_data->mpin = (value << GPIO_DATA_SHIFT);
} }
static void portapack_data_write_high(const uint32_t value) { static void portapack_data_write_high(const uint32_t value)
{
/* NOTE: Assumes no other bits in the port are masked. */ /* NOTE: Assumes no other bits in the port are masked. */
/* NOTE: Assumes that bits 15 through 8 are masked. */ /* NOTE: Assumes that bits 15 through 8 are masked. */
portapack_if.gpio_port_data->mpin = value; portapack_if.gpio_port_data->mpin = value;
} }
static void portapack_dir_read() { static void portapack_dir_read()
{
portapack_if.gpio_port_data->dir &= ~gpio_data_mask; portapack_if.gpio_port_data->dir &= ~gpio_data_mask;
gpio_set(portapack_if.gpio_dir); gpio_set(portapack_if.gpio_dir);
} }
static void portapack_dir_write() { static void portapack_dir_write()
{
gpio_clear(portapack_if.gpio_dir); gpio_clear(portapack_if.gpio_dir);
portapack_if.gpio_port_data->dir |= gpio_data_mask; portapack_if.gpio_port_data->dir |= gpio_data_mask;
/* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin /* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin
@ -93,35 +104,43 @@ static void portapack_dir_write() {
*/ */
} }
__attribute__((unused)) static void portapack_lcd_rd_assert() { __attribute__((unused)) static void portapack_lcd_rd_assert()
{
gpio_clear(portapack_if.gpio_lcd_rdx); gpio_clear(portapack_if.gpio_lcd_rdx);
} }
static void portapack_lcd_rd_deassert() { static void portapack_lcd_rd_deassert()
{
gpio_set(portapack_if.gpio_lcd_rdx); gpio_set(portapack_if.gpio_lcd_rdx);
} }
static void portapack_lcd_wr_assert() { static void portapack_lcd_wr_assert()
{
gpio_clear(portapack_if.gpio_lcd_wrx); gpio_clear(portapack_if.gpio_lcd_wrx);
} }
static void portapack_lcd_wr_deassert() { static void portapack_lcd_wr_deassert()
{
gpio_set(portapack_if.gpio_lcd_wrx); gpio_set(portapack_if.gpio_lcd_wrx);
} }
static void portapack_io_stb_assert() { static void portapack_io_stb_assert()
{
gpio_clear(portapack_if.gpio_io_stbx); gpio_clear(portapack_if.gpio_io_stbx);
} }
static void portapack_io_stb_deassert() { static void portapack_io_stb_deassert()
{
gpio_set(portapack_if.gpio_io_stbx); gpio_set(portapack_if.gpio_io_stbx);
} }
static void portapack_addr(const bool value) { static void portapack_addr(const bool value)
{
gpio_write(portapack_if.gpio_addr, value); gpio_write(portapack_if.gpio_addr, value);
} }
static void portapack_lcd_command(const uint32_t value) { static void portapack_lcd_command(const uint32_t value)
{
portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */ portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */
portapack_dir_write(); /* Turn around data bus, MCU->CPLD */ portapack_dir_write(); /* Turn around data bus, MCU->CPLD */
portapack_addr(0); /* Indicate command */ portapack_addr(0); /* Indicate command */
@ -139,7 +158,8 @@ static void portapack_lcd_command(const uint32_t value) {
portapack_addr(1); /* Set up for data phase (most likely after a command) */ portapack_addr(1); /* Set up for data phase (most likely after a command) */
} }
static void portapack_lcd_write_data(const uint32_t value) { static void portapack_lcd_write_data(const uint32_t value)
{
// NOTE: Assumes and DIR=0 and ADDR=1 from command phase. // NOTE: Assumes and DIR=0 and ADDR=1 from command phase.
portapack_data_write_high(value); /* Drive high byte */ portapack_data_write_high(value); /* Drive high byte */
__asm__("nop"); __asm__("nop");
@ -152,7 +172,8 @@ static void portapack_lcd_write_data(const uint32_t value) {
portapack_lcd_wr_deassert(); /* Complete write operation */ portapack_lcd_wr_deassert(); /* Complete write operation */
} }
static void portapack_io_write(const bool address, const uint_fast16_t value) { static void portapack_io_write(const bool address, const uint_fast16_t value)
{
portapack_data_write_low(value); portapack_data_write_low(value);
portapack_dir_write(); portapack_dir_write();
portapack_addr(address); portapack_addr(address);
@ -166,7 +187,8 @@ static void portapack_io_write(const bool address, const uint_fast16_t value) {
portapack_io_stb_deassert(); portapack_io_stb_deassert();
} }
static void portapack_if_init() { static void portapack_if_init()
{
portapack_data_mask_set(); portapack_data_mask_set();
portapack_data_write_high(0); portapack_data_write_high(0);
@ -202,7 +224,8 @@ static void portapack_if_init() {
/* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ /* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */
} }
static void portapack_lcd_reset_state(const bool active) { static void portapack_lcd_reset_state(const bool active)
{
portapack_if.io_reg = (portapack_if.io_reg & 0xfe) | (active ? (1 << 0) : 0); portapack_if.io_reg = (portapack_if.io_reg & 0xfe) | (active ? (1 << 0) : 0);
portapack_io_write(1, portapack_if.io_reg); portapack_io_write(1, portapack_if.io_reg);
} }
@ -210,15 +233,16 @@ static void portapack_lcd_reset_state(const bool active) {
static void portapack_lcd_data_write_command_and_data( static void portapack_lcd_data_write_command_and_data(
const uint_fast8_t command, const uint_fast8_t command,
const uint8_t* data, const uint8_t* data,
const size_t data_count const size_t data_count)
) { {
portapack_lcd_command(command); portapack_lcd_command(command);
for (size_t i = 0; i < data_count; i++) { for (size_t i = 0; i < data_count; i++) {
portapack_lcd_write_data(data[i]); portapack_lcd_write_data(data[i]);
} }
} }
static void portapack_lcd_sleep_out() { static void portapack_lcd_sleep_out()
{
const uint8_t cmd_11[] = {}; const uint8_t cmd_11[] = {};
portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11)); portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11));
// "It will be necessary to wait 120msec after sending Sleep Out // "It will be necessary to wait 120msec after sending Sleep Out
@ -227,56 +251,68 @@ static void portapack_lcd_sleep_out() {
portapack_sleep_milliseconds(120); portapack_sleep_milliseconds(120);
} }
static void portapack_lcd_display_on() { static void portapack_lcd_display_on()
{
const uint8_t cmd_29[] = {}; const uint8_t cmd_29[] = {};
portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29)); portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29));
} }
static void portapack_lcd_ramwr_start() { static void portapack_lcd_ramwr_start()
{
const uint8_t cmd_2c[] = {}; const uint8_t cmd_2c[] = {};
portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c)); portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c));
} }
static void portapack_lcd_set(const uint_fast8_t command, const uint_fast16_t start, const uint_fast16_t end) { static void portapack_lcd_set(
const uint8_t data[] = { const uint_fast8_t command,
(start >> 8), (start & 0xff), const uint_fast16_t start,
(end >> 8), (end & 0xff) const uint_fast16_t end)
}; {
const uint8_t data[] = {(start >> 8), (start & 0xff), (end >> 8), (end & 0xff)};
portapack_lcd_data_write_command_and_data(command, data, ARRAY_SIZEOF(data)); portapack_lcd_data_write_command_and_data(command, data, ARRAY_SIZEOF(data));
} }
static void portapack_lcd_caset(const uint_fast16_t start_column, const uint_fast16_t end_column) { static void portapack_lcd_caset(
const uint_fast16_t start_column,
const uint_fast16_t end_column)
{
portapack_lcd_set(0x2a, start_column, end_column); portapack_lcd_set(0x2a, start_column, end_column);
} }
static void portapack_lcd_paset(const uint_fast16_t start_page, const uint_fast16_t end_page) { static void portapack_lcd_paset(
const uint_fast16_t start_page,
const uint_fast16_t end_page)
{
portapack_lcd_set(0x2b, start_page, end_page); portapack_lcd_set(0x2b, start_page, end_page);
} }
static void portapack_lcd_start_ram_write( static void portapack_lcd_start_ram_write(const ui_rect_t rect)
const ui_rect_t rect {
) {
portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1); portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1);
portapack_lcd_paset(rect.point.y, rect.point.y + rect.size.height - 1); portapack_lcd_paset(rect.point.y, rect.point.y + rect.size.height - 1);
portapack_lcd_ramwr_start(); portapack_lcd_ramwr_start();
} }
static void portapack_lcd_write_pixel(const ui_color_t pixel) { static void portapack_lcd_write_pixel(const ui_color_t pixel)
{
portapack_lcd_write_data(pixel.v); portapack_lcd_write_data(pixel.v);
} }
static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n) { static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n)
{
while (n--) { while (n--) {
portapack_lcd_write_data(c.v); portapack_lcd_write_data(c.v);
} }
} }
static void portapack_lcd_wake() { static void portapack_lcd_wake()
{
portapack_lcd_sleep_out(); portapack_lcd_sleep_out();
portapack_lcd_display_on(); portapack_lcd_display_on();
} }
static void portapack_lcd_reset() { static void portapack_lcd_reset()
{
portapack_lcd_reset_state(false); portapack_lcd_reset_state(false);
portapack_sleep_milliseconds(1); portapack_sleep_milliseconds(1);
portapack_lcd_reset_state(true); portapack_lcd_reset_state(true);
@ -285,7 +321,8 @@ static void portapack_lcd_reset() {
portapack_sleep_milliseconds(120); portapack_sleep_milliseconds(120);
} }
static void portapack_lcd_init() { static void portapack_lcd_init()
{
// LCDs are configured for IM[2:0] = 001 // LCDs are configured for IM[2:0] = 001
// 8080-I system, 16-bit parallel bus // 8080-I system, 16-bit parallel bus
@ -399,16 +436,40 @@ static void portapack_lcd_init() {
// Set Gamma // Set Gamma
const uint8_t cmd_e0[] = { const uint8_t cmd_e0[] = {
0x0F, 0x1D, 0x19, 0x0E, 0x10, 0x07, 0x4C, 0x63, 0x0F,
0x3F, 0x03, 0x0D, 0x00, 0x26, 0x24, 0x04 0x1D,
}; 0x19,
0x0E,
0x10,
0x07,
0x4C,
0x63,
0x3F,
0x03,
0x0D,
0x00,
0x26,
0x24,
0x04};
portapack_lcd_data_write_command_and_data(0xE0, cmd_e0, ARRAY_SIZEOF(cmd_e0)); portapack_lcd_data_write_command_and_data(0xE0, cmd_e0, ARRAY_SIZEOF(cmd_e0));
// Set Gamma // Set Gamma
const uint8_t cmd_e1[] = { const uint8_t cmd_e1[] = {
0x00, 0x1C, 0x1F, 0x02, 0x0F, 0x03, 0x35, 0x25, 0x00,
0x47, 0x04, 0x0C, 0x0B, 0x29, 0x2F, 0x05 0x1C,
}; 0x1F,
0x02,
0x0F,
0x03,
0x35,
0x25,
0x47,
0x04,
0x0C,
0x0B,
0x29,
0x2F,
0x05};
portapack_lcd_data_write_command_and_data(0xE1, cmd_e1, ARRAY_SIZEOF(cmd_e1)); portapack_lcd_data_write_command_and_data(0xE1, cmd_e1, ARRAY_SIZEOF(cmd_e1));
portapack_lcd_wake(); portapack_lcd_wake();
@ -418,26 +479,27 @@ static void portapack_lcd_init() {
portapack_lcd_data_write_command_and_data(0x35, cmd_35, ARRAY_SIZEOF(cmd_35)); portapack_lcd_data_write_command_and_data(0x35, cmd_35, ARRAY_SIZEOF(cmd_35));
} }
void portapack_backlight(const bool on) { void portapack_backlight(const bool on)
{
portapack_if.io_reg = (portapack_if.io_reg & 0x7f) | (on ? (1 << 7) : 0); portapack_if.io_reg = (portapack_if.io_reg & 0x7f) | (on ? (1 << 7) : 0);
portapack_io_write(1, portapack_if.io_reg); portapack_io_write(1, portapack_if.io_reg);
} }
void portapack_reference_oscillator(const bool on) { void portapack_reference_oscillator(const bool on)
{
const uint8_t mask = 1 << 6; const uint8_t mask = 1 << 6;
portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0); portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0);
portapack_io_write(1, portapack_if.io_reg); portapack_io_write(1, portapack_if.io_reg);
} }
void portapack_fill_rectangle( void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color)
const ui_rect_t rect, {
const ui_color_t color
) {
portapack_lcd_start_ram_write(rect); portapack_lcd_start_ram_write(rect);
portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height); portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height);
} }
void portapack_clear_display(const ui_color_t color) { void portapack_clear_display(const ui_color_t color)
{
const ui_rect_t rect_screen = {{0, 0}, {240, 320}}; const ui_rect_t rect_screen = {{0, 0}, {240, 320}};
portapack_fill_rectangle(rect_screen, color); portapack_fill_rectangle(rect_screen, color);
} }
@ -446,12 +508,9 @@ void portapack_draw_bitmap(
const ui_point_t point, const ui_point_t point,
const ui_bitmap_t bitmap, const ui_bitmap_t bitmap,
const ui_color_t foreground, const ui_color_t foreground,
const ui_color_t background const ui_color_t background)
) { {
const ui_rect_t rect = { const ui_rect_t rect = {.point = point, .size = bitmap.size};
.point = point,
.size = bitmap.size
};
portapack_lcd_start_ram_write(rect); portapack_lcd_start_ram_write(rect);
@ -462,17 +521,14 @@ void portapack_draw_bitmap(
} }
} }
ui_bitmap_t portapack_font_glyph( ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c)
const ui_font_t* const font, {
const char c
) {
if (c >= font->c_start) { if (c >= font->c_start) {
const uint_fast8_t index = c - font->c_start; const uint_fast8_t index = c - font->c_start;
if (index < font->c_count) { if (index < font->c_count) {
const ui_bitmap_t bitmap = { const ui_bitmap_t bitmap = {
.size = font->glyph_size, .size = font->glyph_size,
.data = &font->data[index * font->data_stride] .data = &font->data[index * font->data_stride]};
};
return bitmap; return bitmap;
} }
} }
@ -484,7 +540,8 @@ ui_bitmap_t portapack_font_glyph(
return bitmap; return bitmap;
} }
static bool jtag_pp_tck(const bool tms_value) { static bool jtag_pp_tck(const bool tms_value)
{
gpio_write(jtag_cpld.gpio->gpio_pp_tms, tms_value); gpio_write(jtag_cpld.gpio->gpio_pp_tms, tms_value);
// 8 ns TMS/TDI to TCK setup // 8 ns TMS/TDI to TCK setup
@ -517,7 +574,8 @@ static bool jtag_pp_tck(const bool tms_value) {
return gpio_read(jtag_cpld.gpio->gpio_pp_tdo); return gpio_read(jtag_cpld.gpio->gpio_pp_tdo);
} }
static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) { static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count)
{
uint32_t result = 0; uint32_t result = 0;
size_t bit_in_index = count - 1; size_t bit_in_index = count - 1;
size_t bit_out_index = 0; size_t bit_out_index = 0;
@ -532,7 +590,8 @@ static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) {
return result; return result;
} }
static uint32_t jtag_pp_idcode(void) { static uint32_t jtag_pp_idcode(void)
{
cpld_jtag_take(&jtag_cpld); cpld_jtag_take(&jtag_cpld);
/* TODO: Check if PortaPack TMS is floating or driven by an external device. */ /* TODO: Check if PortaPack TMS is floating or driven by an external device. */
@ -552,20 +611,22 @@ static uint32_t jtag_pp_idcode(void) {
return idcode; return idcode;
} }
static bool portapack_detect(void) { static bool portapack_detect(void)
{
return jtag_pp_idcode() == 0x020A50DD; return jtag_pp_idcode() == 0x020A50DD;
} }
static const portapack_t portapack_instance = { static const portapack_t portapack_instance = {};
};
static const portapack_t* portapack_pointer = NULL; static const portapack_t* portapack_pointer = NULL;
const portapack_t* portapack(void) { const portapack_t* portapack(void)
{
return portapack_pointer; return portapack_pointer;
} }
void portapack_init(void) { void portapack_init(void)
{
if (portapack_detect()) { if (portapack_detect()) {
portapack_if_init(); portapack_if_init();
portapack_lcd_reset(); portapack_lcd_reset();

View File

@ -73,10 +73,7 @@ void portapack_backlight(const bool on);
void portapack_reference_oscillator(const bool on) __attribute__((weak)); void portapack_reference_oscillator(const bool on) __attribute__((weak));
void portapack_fill_rectangle( void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color);
const ui_rect_t rect,
const ui_color_t color
);
void portapack_clear_display(const ui_color_t color); void portapack_clear_display(const ui_color_t color);
@ -84,12 +81,8 @@ void portapack_draw_bitmap(
const ui_point_t point, const ui_point_t point,
const ui_bitmap_t bitmap, const ui_bitmap_t bitmap,
const ui_color_t foreground, const ui_color_t foreground,
const ui_color_t background const ui_color_t background);
);
ui_bitmap_t portapack_font_glyph( ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c);
const ui_font_t* const font,
const char c
);
#endif /*__PORTAPACK_H__*/ #endif /*__PORTAPACK_H__*/

View File

@ -104,13 +104,10 @@ uint8_t *rad1o_pk_decode(const uint8_t *ldata, int *len)
if (pos == 8) { if (pos == 8) {
bufptr++; bufptr++;
if ((bufptr - charBuf) % height == if ((bufptr - charBuf) % height == 0) { // End of column?
0) { // End of column?
while (repeat > 0) { while (repeat > 0) {
for (int y = 0; y < height; for (int y = 0; y < height; y++) {
y++) { bufptr[0] = bufptr[-height];
bufptr[0] =
bufptr[-height];
bufptr++; bufptr++;
}; };
repeat--; repeat--;

View File

@ -44,9 +44,16 @@ static void select()
uint8_t serial_clock_rate = 1; uint8_t serial_clock_rate = 1;
uint8_t clock_prescale_rate = 12; uint8_t clock_prescale_rate = 12;
ssp_init(LCD_SSP, SSP_DATA_9BITS, SSP_FRAME_SPI, SSP_CPOL_0_CPHA_0, ssp_init(
serial_clock_rate, clock_prescale_rate, SSP_MODE_NORMAL, LCD_SSP,
SSP_MASTER, SSP_SLAVE_OUT_ENABLE); SSP_DATA_9BITS,
SSP_FRAME_SPI,
SSP_CPOL_0_CPHA_0,
serial_clock_rate,
clock_prescale_rate,
SSP_MODE_NORMAL,
SSP_MASTER,
SSP_SLAVE_OUT_ENABLE);
gpio_clear(&gpio_lcd_cs); gpio_clear(&gpio_lcd_cs);
} }
@ -87,17 +94,24 @@ void rad1o_lcdInit(void)
/* The controller is a PCF8833 - documentation can be found online. */ /* The controller is a PCF8833 - documentation can be found online. */
static uint8_t initseq_d[] = { static uint8_t initseq_d[] = {
0x11, // SLEEP_OUT (wake up) 0x11, // SLEEP_OUT (wake up)
0x3A, 2, // mode 8bpp (2= 8bpp, 3= 12bpp, 5= 16bpp) 0x3A,
0x36, 0b11000000, // my,mx,v,lao,rgb,x,x,x 2, // mode 8bpp (2= 8bpp, 3= 12bpp, 5= 16bpp)
0x25, 0x3a, // set contrast 0x36,
0b11000000, // my,mx,v,lao,rgb,x,x,x
0x25,
0x3a, // set contrast
0x29, // display on 0x29, // display on
0x03, // BSTRON (booster voltage) 0x03, // BSTRON (booster voltage)
0x2A, 1, RESX, 0x2B, 1, RESY 0x2A,
}; 1,
uint16_t initseq_c = ~(/* commands: 1, data: 0 */ RESX,
(1 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | 0x2B,
(0 << 4) | (1 << 5) | (0 << 6) | (1 << 7) | 1,
(1 << 8) | (1 << 9) | (0 << 10) | (0 << 11) | RESY};
uint16_t initseq_c =
~(/* commands: 1, data: 0 */
(1 << 0) | (1 << 1) | (0 << 2) | (1 << 3) | (0 << 4) | (1 << 5) |
(0 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 11) |
(1 << 12) | (0 << 13) | (0 << 14) | 0); (1 << 12) | (0 << 13) | (0 << 14) | 0);
write(0, 0x01); /* most color displays need the pause */ write(0, 0x01); /* most color displays need the pause */

View File

@ -98,8 +98,7 @@ int rad1o_DoChar(int sx, int sy, int c)
data = &font->au8FontTable[toff + 3]; data = &font->au8FontTable[toff + 3];
width = (width - 3 / height); width = (width - 3 / height);
} else { } else {
data = rad1o_pk_decode( data = rad1o_pk_decode(&font->au8FontTable[toff], &width);
&font->au8FontTable[toff], &width);
} }
} else { } else {
toff = (c) *font->u8Width * 1; toff = (c) *font->u8Width * 1;
@ -109,8 +108,7 @@ int rad1o_DoChar(int sx, int sy, int c)
} while (0); } while (0);
#define xy_(x, y) \ #define xy_(x, y) ((x < 0 || y < 0 || x >= RESX || y >= RESY) ? 0 : (y) *RESX + (x))
((x < 0 || y < 0 || x >= RESX || y >= RESY) ? 0 : (y)*RESX + (x))
#define gPx(x, y) (data[x * height + (height - y / 8 - 1)] & (1 << (y % 8))) #define gPx(x, y) (data[x * height + (height - y / 8 - 1)] & (1 << (y % 8)))
int x = 0; int x = 0;

View File

@ -3399,11 +3399,11 @@ const FONT_CHAR_INFO Ubuntu18ptLengths[] = {
{30}, /* € */ {30}, /* € */
}; };
const uint16_t Ubuntu18ptExtra[] = { 196, 214, 220, 223, 228, const uint16_t Ubuntu18ptExtra[] = {196, 214, 220, 223, 228, 246, 252, 8364, 65535};
246, 252, 8364, 65535 };
/* Font info */ /* Font info */
const struct FONT_DEF Font_Ubuntu18pt = { 1, /* width (1 == comressed) */ const struct FONT_DEF Font_Ubuntu18pt = {
1, /* width (1 == comressed) */
26, /* character height */ 26, /* character height */
32, /* first char */ 32, /* first char */
126, /* last char */ 126, /* last char */

View File

@ -74,7 +74,9 @@
* Safe (initial) switch settings turn off both amplifiers and enable both amp * Safe (initial) switch settings turn off both amplifiers and enable both amp
* bypass and mixer bypass. * bypass and mixer bypass.
*/ */
#define SWITCHCTRL_SAFE (SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR) #define SWITCHCTRL_SAFE \
(SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | \
SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR)
#endif #endif
uint8_t switchctrl = SWITCHCTRL_SAFE; uint8_t switchctrl = SWITCHCTRL_SAFE;
@ -88,7 +90,8 @@ uint8_t switchctrl = SWITCHCTRL_SAFE;
#define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl)
{
if (ctrl & SWITCHCTRL_TX) { if (ctrl & SWITCHCTRL_TX) {
gpio_set(rf_path->gpio_tx); gpio_set(rf_path->gpio_tx);
gpio_clear(rf_path->gpio_rx); gpio_clear(rf_path->gpio_rx);
@ -147,10 +150,12 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) {
* used to explicitly turn off power to the amplifiers while AMP_BYPASS * used to explicitly turn off power to the amplifiers while AMP_BYPASS
* is unset: * is unset:
*/ */
if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR) if (ctrl & SWITCHCTRL_NO_TX_AMP_PWR) {
gpio_set(rf_path->gpio_no_tx_amp_pwr); gpio_set(rf_path->gpio_no_tx_amp_pwr);
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR) }
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR) {
gpio_set(rf_path->gpio_no_rx_amp_pwr); gpio_set(rf_path->gpio_no_rx_amp_pwr);
}
if (ctrl & SWITCHCTRL_ANT_PWR) { if (ctrl & SWITCHCTRL_ANT_PWR) {
mixer_set_gpo(&mixer, 0x00); /* turn on antenna power by clearing GPO1 */ mixer_set_gpo(&mixer, 0x00); /* turn on antenna power by clearing GPO1 */
@ -161,7 +166,8 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) {
#endif #endif
#ifdef RAD1O #ifdef RAD1O
static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) { static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl)
{
if (ctrl & SWITCHCTRL_TX) { if (ctrl & SWITCHCTRL_TX) {
gpio_set(rf_path->gpio_tx_rx_n); gpio_set(rf_path->gpio_tx_rx_n);
gpio_clear(rf_path->gpio_tx_rx); gpio_clear(rf_path->gpio_tx_rx);
@ -224,7 +230,8 @@ static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) {
} }
#endif #endif
static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) { static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo)
{
#ifdef JAWBREAKER #ifdef JAWBREAKER
(void) rf_path; /* silence unused param warning */ (void) rf_path; /* silence unused param warning */
mixer_set_gpo(&mixer, gpo); mixer_set_gpo(&mixer, gpo);
@ -237,9 +244,11 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) {
#endif #endif
} }
void rf_path_pin_setup(rf_path_t* const rf_path) { void rf_path_pin_setup(rf_path_t* const rf_path)
{
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
/* Configure RF switch control signals */ /* Configure RF switch control signals */
// clang-format off
scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_HP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_LP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_TX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -253,6 +262,7 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_AMP_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_RX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
// clang-format on
/* Configure RF power supply (VAA) switch */ /* Configure RF power supply (VAA) switch */
scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -279,6 +289,7 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS); switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
#elif RAD1O #elif RAD1O
/* Configure RF switch control signals */ /* Configure RF switch control signals */
// clang-format off
scu_pinmux(SCU_BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_BY_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_BY_AMP_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -290,6 +301,7 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_RX_LNA, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
// clang-format on
/* Configure RF power supply (VAA) switch */ /* Configure RF power supply (VAA) switch */
scu_pinmux(SCU_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -317,7 +329,8 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
#endif #endif
} }
void rf_path_init(rf_path_t* const rf_path) { void rf_path_init(rf_path_t* const rf_path)
{
ssp1_set_mode_max5864(); ssp1_set_mode_max5864();
max5864_setup(&max5864); max5864_setup(&max5864);
max5864_shutdown(&max5864); max5864_shutdown(&max5864);
@ -330,7 +343,8 @@ void rf_path_init(rf_path_t* const rf_path) {
switchctrl_set(rf_path, switchctrl); switchctrl_set(rf_path, switchctrl);
} }
void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction) { void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction)
{
/* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */ /* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
switch (direction) { switch (direction) {
@ -394,7 +408,8 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
hackrf_ui()->set_direction(direction); hackrf_ui()->set_direction(direction);
} }
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) { void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
{
switch (filter) { switch (filter) {
default: default:
case RF_PATH_FILTER_BYPASS: case RF_PATH_FILTER_BYPASS:
@ -419,20 +434,24 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
hackrf_ui()->set_filter(filter); hackrf_ui()->set_filter(filter);
} }
void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) { void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable)
{
if (enable) { if (enable) {
if (rf_path->switchctrl & SWITCHCTRL_TX) { if (rf_path->switchctrl & SWITCHCTRL_TX) {
/* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */ /* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */
rf_path->switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR;
rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR); rf_path->switchctrl &=
~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
} else { } else {
/* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */ /* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR;
rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR); rf_path->switchctrl &=
~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
} }
} else { } else {
/* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */ /* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */
rf_path->switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR |
SWITCHCTRL_NO_RX_AMP_PWR;
} }
switchctrl_set(rf_path, rf_path->switchctrl); switchctrl_set(rf_path, rf_path->switchctrl);
@ -441,7 +460,8 @@ void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) {
} }
/* antenna port power control */ /* antenna port power control */
void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable) { void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable)
{
if (enable) { if (enable) {
rf_path->switchctrl |= SWITCHCTRL_ANT_PWR; rf_path->switchctrl |= SWITCHCTRL_ANT_PWR;
} else { } else {

View File

@ -70,7 +70,8 @@ static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
0x0000, /* 1B */ 0x0000, /* 1B */
0xc840, /* 1C */ 0xc840, /* 1C */
0x1000, /* 1D */ 0x1000, /* 1D */
0x0005, /* 1E */ }; 0x0005,
/* 1E */};
/* Set up all registers according to defaults specified in docs. */ /* Set up all registers according to defaults specified in docs. */
void rffc5071_init(rffc5071_driver_t* const drv) void rffc5071_init(rffc5071_driver_t* const drv)
@ -120,7 +121,8 @@ void rffc5071_setup(rffc5071_driver_t* const drv)
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r)
{
(void) drv; (void) drv;
uint16_t data[] = {0x80 | (r & 0x7f), 0xffff}; uint16_t data[] = {0x80 | (r & 0x7f), 0xffff};
@ -128,7 +130,8 @@ static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) {
return data[1]; return data[1];
} }
static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v)
{
(void) drv; (void) drv;
uint16_t data[] = {0x00 | (r & 0x7f), v}; uint16_t data[] = {0x00 | (r & 0x7f), v};
@ -138,8 +141,9 @@ static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t
uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r) uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r)
{ {
/* Readback register is not cached. */ /* Readback register is not cached. */
if (r == RFFC5071_READBACK_REG) if (r == RFFC5071_READBACK_REG) {
return rffc5071_spi_read(drv, r); return rffc5071_spi_read(drv, r);
}
/* Discard uncommited write when reading. This shouldn't /* Discard uncommited write when reading. This shouldn't
* happen, and probably has not been tested. */ * happen, and probably has not been tested. */
@ -171,14 +175,16 @@ void rffc5071_regs_commit(rffc5071_driver_t* const drv)
} }
} }
void rffc5071_tx(rffc5071_driver_t* const drv) { void rffc5071_tx(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 0); set_RFFC5071_FULLD(drv, 0);
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
void rffc5071_rx(rffc5071_driver_t* const drv) { void rffc5071_rx(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 0); set_RFFC5071_FULLD(drv, 0);
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
@ -189,7 +195,8 @@ void rffc5071_rx(rffc5071_driver_t* const drv) {
* This function turns on both mixer (full-duplex) on the RFFC5071, but our * This function turns on both mixer (full-duplex) on the RFFC5071, but our
* current hardware designs do not support full-duplex operation. * current hardware designs do not support full-duplex operation.
*/ */
void rffc5071_rxtx(rffc5071_driver_t* const drv) { void rffc5071_rxtx(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */ set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
@ -197,12 +204,14 @@ void rffc5071_rxtx(rffc5071_driver_t* const drv) {
rffc5071_enable(drv); rffc5071_enable(drv);
} }
void rffc5071_disable(rffc5071_driver_t* const drv) { void rffc5071_disable(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
void rffc5071_enable(rffc5071_driver_t* const drv) { void rffc5071_enable(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 1); set_RFFC5071_ENBL(drv, 1);
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
@ -212,7 +221,8 @@ void rffc5071_enable(rffc5071_driver_t* const drv) {
#define FREQ_ONE_MHZ (1000 * 1000) #define FREQ_ONE_MHZ (1000 * 1000)
/* configure frequency synthesizer in integer mode (lo in MHz) */ /* configure frequency synthesizer in integer mode (lo in MHz) */
uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) { uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo)
{
uint8_t lodiv; uint8_t lodiv;
uint16_t fvco; uint16_t fvco;
uint8_t fbkdiv; uint8_t fbkdiv;
@ -251,8 +261,8 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
p1nmsb = (tmp_n >> 13ULL) & 0xffff; p1nmsb = (tmp_n >> 13ULL) & 0xffff;
p1nlsb = (tmp_n >> 5ULL) & 0xff; p1nlsb = (tmp_n >> 5ULL) & 0xff;
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ) tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ) /
/ (lodiv * (1 << 24ULL)); (lodiv * (1 << 24ULL));
/* Path 2 */ /* Path 2 */
set_RFFC5071_P2LODIV(drv, n_lo); set_RFFC5071_P2LODIV(drv, n_lo);
@ -267,7 +277,8 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
} }
/* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */ /* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */
uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint16_t mhz) { uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint16_t mhz)
{
uint32_t tune_freq; uint32_t tune_freq;
rffc5071_disable(drv); rffc5071_disable(drv);

View File

@ -25,37 +25,44 @@
#include "rffc5071_spi.h" #include "rffc5071_spi.h"
static void rffc5071_spi_target_select(spi_bus_t* const bus) { static void rffc5071_spi_target_select(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
gpio_clear(config->gpio_select); gpio_clear(config->gpio_select);
} }
static void rffc5071_spi_target_unselect(spi_bus_t* const bus) { static void rffc5071_spi_target_unselect(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
gpio_set(config->gpio_select); gpio_set(config->gpio_select);
} }
static void rffc5071_spi_direction_out(spi_bus_t* const bus) { static void rffc5071_spi_direction_out(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
gpio_output(config->gpio_data); gpio_output(config->gpio_data);
} }
static void rffc5071_spi_direction_in(spi_bus_t* const bus) { static void rffc5071_spi_direction_in(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
gpio_input(config->gpio_data); gpio_input(config->gpio_data);
} }
static void rffc5071_spi_data_out(spi_bus_t* const bus, const bool bit) { static void rffc5071_spi_data_out(spi_bus_t* const bus, const bool bit)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
gpio_write(config->gpio_data, bit); gpio_write(config->gpio_data, bit);
} }
static bool rffc5071_spi_data_in(spi_bus_t* const bus) { static bool rffc5071_spi_data_in(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
return gpio_read(config->gpio_data); return gpio_read(config->gpio_data);
} }
static void rffc5071_spi_bus_init(spi_bus_t* const bus) { static void rffc5071_spi_bus_init(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); scu_pinmux(SCU_MIXER_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
@ -68,7 +75,8 @@ static void rffc5071_spi_bus_init(spi_bus_t* const bus) {
gpio_clear(config->gpio_data); gpio_clear(config->gpio_data);
} }
static void rffc5071_spi_target_init(spi_bus_t* const bus) { static void rffc5071_spi_target_init(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
/* Configure GPIO pins. */ /* Configure GPIO pins. */
@ -82,22 +90,26 @@ static void rffc5071_spi_target_init(spi_bus_t* const bus) {
rffc5071_spi_target_unselect(bus); rffc5071_spi_target_unselect(bus);
} }
void rffc5071_spi_start(spi_bus_t* const bus, const void* const config) { void rffc5071_spi_start(spi_bus_t* const bus, const void* const config)
{
bus->config = config; bus->config = config;
rffc5071_spi_bus_init(bus); rffc5071_spi_bus_init(bus);
rffc5071_spi_target_init(bus); rffc5071_spi_target_init(bus);
} }
void rffc5071_spi_stop(spi_bus_t* const bus) { void rffc5071_spi_stop(spi_bus_t* const bus)
{
(void) bus; (void) bus;
} }
static void rffc5071_spi_serial_delay(spi_bus_t* const bus) { static void rffc5071_spi_serial_delay(spi_bus_t* const bus)
{
(void) bus; (void) bus;
__asm__("nop"); __asm__("nop");
} }
static void rffc5071_spi_sck(spi_bus_t* const bus) { static void rffc5071_spi_sck(spi_bus_t* const bus)
{
const rffc5071_spi_config_t* const config = bus->config; const rffc5071_spi_config_t* const config = bus->config;
rffc5071_spi_serial_delay(bus); rffc5071_spi_serial_delay(bus);
@ -107,13 +119,18 @@ static void rffc5071_spi_sck(spi_bus_t* const bus) {
gpio_clear(config->gpio_clock); gpio_clear(config->gpio_clock);
} }
static uint32_t rffc5071_spi_exchange_bit(spi_bus_t* const bus, const uint32_t bit) { static uint32_t rffc5071_spi_exchange_bit(spi_bus_t* const bus, const uint32_t bit)
{
rffc5071_spi_data_out(bus, bit); rffc5071_spi_data_out(bus, bit);
rffc5071_spi_sck(bus); rffc5071_spi_sck(bus);
return rffc5071_spi_data_in(bus) ? 1 : 0; return rffc5071_spi_data_in(bus) ? 1 : 0;
} }
static uint32_t rffc5071_spi_exchange_word(spi_bus_t* const bus, const uint32_t data, const size_t count) { static uint32_t rffc5071_spi_exchange_word(
spi_bus_t* const bus,
const uint32_t data,
const size_t count)
{
size_t bits = count; size_t bits = count;
const uint32_t msb = 1UL << (count - 1); const uint32_t msb = 1UL << (count - 1);
uint32_t t = data; uint32_t t = data;
@ -141,7 +158,8 @@ static uint32_t rffc5071_spi_exchange_word(spi_bus_t* const bus, const uint32_t
* next 7 bits are register address, * next 7 bits are register address,
* next 16 bits are register value. * next 16 bits are register value.
*/ */
void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t count) { void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t count)
{
if (count != 2) { if (count != 2) {
return; return;
} }
@ -177,7 +195,11 @@ void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t
rffc5071_spi_sck(bus); rffc5071_spi_sck(bus);
} }
void rffc5071_spi_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfer, const size_t count) { void rffc5071_spi_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfer,
const size_t count)
{
if (count == 1) { if (count == 1) {
rffc5071_spi_transfer(bus, transfer[0].data, transfer[0].count); rffc5071_spi_transfer(bus, transfer[0].data, transfer[0].count);
} }

View File

@ -36,6 +36,9 @@ typedef struct rffc5071_spi_config_t {
void rffc5071_spi_start(spi_bus_t* const bus, const void* const config); void rffc5071_spi_start(spi_bus_t* const bus, const void* const config);
void rffc5071_spi_stop(spi_bus_t* const bus); void rffc5071_spi_stop(spi_bus_t* const bus);
void rffc5071_spi_transfer(spi_bus_t* const bus, void* const data, const size_t count); void rffc5071_spi_transfer(spi_bus_t* const bus, void* const data, const size_t count);
void rffc5071_spi_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfer, const size_t count); void rffc5071_spi_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfer,
const size_t count);
#endif // __RFFC5071_SPI_H #endif // __RFFC5071_SPI_H

View File

@ -36,6 +36,7 @@ typedef struct {
const IAP_t IAP; /* If equal to 0x12345678 IAP not implemented */ const IAP_t IAP; /* If equal to 0x12345678 IAP not implemented */
/* Other TBD */ /* Other TBD */
} * pENTRY_ROM_API_t; } * pENTRY_ROM_API_t;
#define pROM_API ((pENTRY_ROM_API_t) ROM_IAP_ADDR) #define pROM_API ((pENTRY_ROM_API_t) ROM_IAP_ADDR)
/* /*
@ -54,11 +55,9 @@ typedef struct {
bool iap_is_implemented(void) bool iap_is_implemented(void)
{ {
bool res; bool res;
if( *((uint32_t*)ROM_IAP_ADDR) != ROM_IAP_UNDEF_ADDR ) if (*((uint32_t*) ROM_IAP_ADDR) != ROM_IAP_UNDEF_ADDR) {
{
res = true; res = true;
}else } else {
{
res = false; res = false;
} }
return res; return res;
@ -68,11 +67,11 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
{ {
uint32_t* p_u32_data; uint32_t* p_u32_data;
if( iap_is_implemented() ) if (iap_is_implemented()) {
{ pROM_API->IAP(
pROM_API->IAP( (uint32_t*)&iap_cmd_res->cmd_param, (uint32_t*)&iap_cmd_res->status_res); (uint32_t*) &iap_cmd_res->cmd_param,
}else (uint32_t*) &iap_cmd_res->status_res);
{ } else {
/* /*
Alternative way to retrieve Part Id on MCU with no IAP Alternative way to retrieve Part Id on MCU with no IAP
Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV
@ -80,8 +79,7 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
w25q80bv_setup(&spi_flash); w25q80bv_setup(&spi_flash);
switch(iap_cmd_res->cmd_param.command_code) switch (iap_cmd_res->cmd_param.command_code) {
{
case IAP_CMD_READ_PART_ID_NO: case IAP_CMD_READ_PART_ID_NO:
p_u32_data = (uint32_t*) ROM_OTP_PART_ID_ADDR; p_u32_data = (uint32_t*) ROM_OTP_PART_ID_ADDR;
iap_cmd_res->status_res.iap_result[0] = p_u32_data[0]; iap_cmd_res->status_res.iap_result[0] = p_u32_data[0];
@ -93,7 +91,10 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
/* Only 64bits used */ /* Only 64bits used */
iap_cmd_res->status_res.iap_result[0] = 0; iap_cmd_res->status_res.iap_result[0] = 0;
iap_cmd_res->status_res.iap_result[1] = 0; iap_cmd_res->status_res.iap_result[1] = 0;
w25q80bv_get_unique_id(&spi_flash, (w25q80bv_unique_id_t*)&iap_cmd_res->status_res.iap_result[2] ); w25q80bv_get_unique_id(
&spi_flash,
(w25q80bv_unique_id_t*) &iap_cmd_res->status_res
.iap_result[2]);
iap_cmd_res->status_res.status_ret = CMD_SUCCESS; iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
break; break;

View File

@ -23,52 +23,53 @@
#define __ROM_IAP__ #define __ROM_IAP__
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
typedef enum typedef enum {
{
/* TODO define other commands */ /* TODO define other commands */
IAP_CMD_INIT_IAP = 49, IAP_CMD_INIT_IAP = 49,
/* Command Init IAP /* Command Init IAP
Input Command code: 49 (decimal) Input: Command code: 49 (decimal)
Return Code CMD_SUCCESS Return Code: CMD_SUCCESS
Result None Result: None
Description Initializes and prepares the flash for erase and write operations. Description Initializes and prepares the flash for erase and write operations.
Stack usage 88 B */ Stack usage 88 B */
IAP_CMD_READ_PART_ID_NO = 54, IAP_CMD_READ_PART_ID_NO = 54,
/* Read part identification number /* Read part identification number
Command Read part identification number Input: Command code: 54 (decimal)
Input Command code: 54 (decimal)
Parameters:None Parameters:None
Return Code CMD_SUCCESS | Return Code: CMD_SUCCESS
Result Result0:Part Identification Number. Result Result0:Part Identification Number.
Result1:Part Identification Number. Result1:Part Identification Number.
Description This command is used to read the part identification number. See Table 1082 Description: This command is used to read the part identification number. See Table 1082
LPC43xx part identification numbers. 'LPC43xx part identification numbers'. The command returns two words: word0
The command returns two words: word0 followed by word1. Word 0 corresponds followed by word1. Word 0 corresponds to the part id and word1 indicates the flash
to the part id and word1 indicates the flash configuration or contains 0x0 for configuration or contains 0x0 for flashless parts.
flashless parts. Stack usage: 8 B */
Stack usage 8 B */
IAP_CMD_READ_SERIAL_NO = 58 IAP_CMD_READ_SERIAL_NO = 58
/* Read device serial number /* Read device serial number
Input Command code: 58 (decimal) Input: Command code: 58 (decimal)
Parameters: None Parameters: None
Return Code CMD_SUCCESS Return Code: CMD_SUCCESS
Result Result0:First 32-bit word of Device Identification Number (at the lowest address) Result: Result0: First 32-bit word of Device Identification Number (at the lowest address)
Result1: Second 32-bit word of Device Identification Number Result1: Second 32-bit word of Device Identification Number
Result2: Third 32-bit word of Device Identification Number Result2: Third 32-bit word of Device Identification Number
Result3: Fourth 32-bit word of Device Identification Number Result3: Fourth 32-bit word of Device Identification Number
Description This command is used to read the device identification number. The serial number Description: This command is used to read the device identification number. The serial number
may be used to uniquely identify a single unit among all LPC43xx devices. may be used to uniquely identify a single unit among all LPC43xx devices.
Stack usage 8 B */ Stack usage: 8 B */
} iap_cmd_code_t; } iap_cmd_code_t;
/* ISP/IAP Return Code */ /* ISP/IAP Return Code */
// clang-format off
typedef enum typedef enum
{ {
CMD_SUCCESS = 0x00000000, /* CMD_SUCCESS Command is executed successfully. Sent by ISP handler only when command given by the host has been completely and successfully executed. */ CMD_SUCCESS = 0x00000000, /* CMD_SUCCESS Command is executed successfully.
Sent by ISP handler only when command given by the host has been completely and successfully executed. */
INVALID_COMMAND = 0x00000001, /* Invalid command. */ INVALID_COMMAND = 0x00000001, /* Invalid command. */
SRC_ADDR_ERROR = 0x00000002, /* Source address is not on word boundary. */ SRC_ADDR_ERROR = 0x00000002, /* Source address is not on word boundary. */
DST_ADDR_ERROR = 0x00000003, /* Destination address not on word or 256 byte boundary. */ DST_ADDR_ERROR = 0x00000003, /* Destination address not on word or 256 byte boundary. */
@ -96,18 +97,17 @@ typedef enum
ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */ ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */
} isp_iap_ret_code_t; } isp_iap_ret_code_t;
typedef struct // clang-format on
{
typedef struct {
/* Input Command/Param */ /* Input Command/Param */
struct struct {
{
iap_cmd_code_t command_code; iap_cmd_code_t command_code;
uint32_t iap_param[5]; uint32_t iap_param[5];
} cmd_param; } cmd_param;
/* Output Status/Result */ /* Output Status/Result */
struct struct {
{
isp_iap_ret_code_t status_ret; isp_iap_ret_code_t status_ret;
uint32_t iap_result[4]; uint32_t iap_result[4];
} status_res; } status_res;

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,8 @@
static void update_q_invert(sgpio_config_t* const config); static void update_q_invert(sgpio_config_t* const config);
#endif #endif
void sgpio_configure_pin_functions(sgpio_config_t* const config) { void sgpio_configure_pin_functions(sgpio_config_t* const config)
{
scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
@ -57,39 +58,58 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) {
gpio_output(config->gpio_hw_sync_enable); gpio_output(config->gpio_hw_sync_enable);
} }
void sgpio_set_slice_mode( void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice)
sgpio_config_t* const config, {
const bool multi_slice
) {
config->slice_mode_multislice = multi_slice; config->slice_mode_multislice = multi_slice;
} }
/* /*
SGPIO0 to 7 = DAC/ADC data bits 0 to 7 (Nota: DAC is 10bits but only bit9 to bit2 are used bit1 & 0 are forced to 0 by CPLD) SGPIO 0 to 7 = DAC/ADC data bits 0 to 7
ADC=> CLK x 2=CLKx2 with CLKx2(0)rising=D0Q, CLKx2(1)rising=D1I (corresponds to CLK(0)falling+tD0Q=>D0Q, CLK(1)rising+tDOI=>D1I, CLK(1)falling+tD0Q=>D1Q, CLK(1)rising+tDOI=>D2I ...) (Note: DAC is 10 bits but only bit 9 to bit 2 are used, bits 1 & 0 are forced to 0 by CPLD)
tDOI(CLK Rise to I-ADC Channel-I Output Data Valid)=7.4 to 9ns, tD0Q(CLK Fall to Q-ADC Channel-Q Output Data Valid)=6.9 to 9ns
DAC=> CLK x 2=CLKx2 with CLKx2(0)rising=Q:N-2, CLKx2(1)rising=I:N-1(corresponds to CLK(0)rising=>Q:N-2, CLK(0)falling I:N-1, CLK(1)rising=>Q:N-1, CLK(1)falling I:N ...) ADC => CLK x 2 = CLKx2 with
tDSI(I-DAC Data to CLK Fall Setup Time)=min 10ns, tDSQ(Q-DAC Data to CLK Rise Setup Time)=min 10ns CLKx2(0) rising = D0Q,
CLKx2(1) rising = D1I
Corresponds to:
CLK(0) falling + tD0Q => D0Q,
CLK(1) rising + tDOI => D1I,
CLK(1) falling + tD0Q => D1Q,
CLK(1) rising + tDOI => D2I ...)
tDOI(CLK Rise to I-ADC Channel-I Output Data Valid) = 7.4 to 9ns
tD0Q(CLK Fall to Q-ADC Channel-Q Output Data Valid) = 6.9 to 9ns
DAC=> CLK x 2 = CLKx2 with:
CLKx2(0) rising = Q:N-2,
CLKx2(1) rising = I:N-1
Corresponds to:
CLK(0) rising => Q:N-2,
CLK(0) falling => I:N-1,
CLK(1) rising => Q:N-1,
CLK(1) falling => I:N ...
tDSI(I-DAC Data to CLK Fall Setup Time) = min 10ns
tDSQ(Q-DAC Data to CLK Rise Setup Time) = min 10ns
SGPIO8 Clock Input (External Clock) SGPIO8 Clock Input (External Clock)
SGPIO9 Capture Input (Capture/ChipSelect, 1=Enable Capture, 0=Disable capture) SGPIO9 Capture Input (Capture/ChipSelect, 1=Enable Capture, 0=Disable capture)
SGPIO10 Disable Output (1/High=Disable codec data stream, 0/Low=Enable codec data stream) SGPIO10 Disable Output (1/High=Disable codec data stream, 0/Low=Enable codec data stream)
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC) SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
*/ */
void sgpio_configure( void sgpio_configure(sgpio_config_t* const config, const sgpio_direction_t direction)
sgpio_config_t* const config, {
const sgpio_direction_t direction
) {
// Disable all counters during configuration // Disable all counters during configuration
SGPIO_CTRL_ENABLE = 0; SGPIO_CTRL_ENABLE = 0;
// Set SGPIO output values. // Set SGPIO output values.
const uint_fast8_t cpld_direction = const uint_fast8_t cpld_direction = (direction == SGPIO_DIRECTION_TX) ? 1 : 0;
(direction == SGPIO_DIRECTION_TX) ? 1 : 0;
// clang-format off
SGPIO_GPIO_OUTREG = SGPIO_GPIO_OUTREG =
(cpld_direction << 11) /* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode)*/ (cpld_direction << 11) // 1 = Output SGPIO11 High (TX mode)
| (1L << 10) // disable codec data stream during configuration (Output SGPIO10 High) // 0 = Output SGPIO11 Low (RX mode)
| (1L << 10) // disable codec data stream during configuration
// (Output SGPIO10 High)
; ;
// clang-format on
#ifdef RAD1O #ifdef RAD1O
/* The data direction might have changed. Check if we need to /* The data direction might have changed. Check if we need to
@ -99,48 +119,49 @@ void sgpio_configure(
// Enable SGPIO pin outputs. // Enable SGPIO pin outputs.
const uint_fast16_t sgpio_gpio_data_direction = const uint_fast16_t sgpio_gpio_data_direction =
(direction == SGPIO_DIRECTION_TX) (direction == SGPIO_DIRECTION_TX) ? (0xFF << 0) : (0x00 << 0);
? (0xFF << 0)
: (0x00 << 0); // clang-format off
SGPIO_GPIO_OENREG = SGPIO_GPIO_OENREG =
(1L << 14) // GPDMA burst request SGPIO14 active (1L << 14) // GPDMA burst request SGPIO14 active
| (1L << 11) // direction output SGPIO11 active | (1L << 11) // direction output SGPIO11 active
| (1L << 10) // disable output SGPIO10 active | (1L << 10) // disable output SGPIO10 active
| (0L << 9) // capture input SGPIO9 (output i is tri-stated) | (0L << 9) // capture input SGPIO9 (output i is tri-stated)
| (0L << 8) // clock input SGPIO8 (output i is tri-stated) | (0L << 8) // clock input SGPIO8 (output i is tri-stated)
| sgpio_gpio_data_direction // 0xFF=Output all SGPIO High(TX mode), 0x00=Output all SPGIO Low(RX mode) | sgpio_gpio_data_direction // 0xFF = Output all SGPIO High (TX mode)
; ; // 0x00 = Output all SPGIO Low (RX mode)
SGPIO_OUT_MUX_CFG( 8) = // SGPIO8: Input: clock SGPIO_OUT_MUX_CFG( 8) = // SGPIO8:
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */ SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */ | SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) // dout_doutm1 (1-bit mode)
; ;
SGPIO_OUT_MUX_CFG( 9) = // SGPIO9: Input: qualifier SGPIO_OUT_MUX_CFG( 9) = // SGPIO9: Input: qualifier
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */ SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */ | SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) // dout_doutm1 (1-bit mode)
; ;
SGPIO_OUT_MUX_CFG(10) = // GPIO10: Output: disable SGPIO_OUT_MUX_CFG(10) = // GPIO10: Output: disable
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */ SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) /* 0x4=gpio_out (level set by GPIO_OUTREG) */ | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) // gpio_out (level set by GPIO_OUTREG)
; ;
SGPIO_OUT_MUX_CFG(11) = // GPIO11: Output: direction SGPIO_OUT_MUX_CFG(11) = // GPIO11: Output: direction
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */ SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) /* 0x4=gpio_out (level set by GPIO_OUTREG) */ | SGPIO_OUT_MUX_CFG_P_OUT_CFG(4) // gpio_out (level set by GPIO_OUTREG)
; ;
SGPIO_OUT_MUX_CFG(14) = // SGPIO14: Output: internal GPDMA burst request SGPIO_OUT_MUX_CFG(14) = // SGPIO14: Output: internal GPDMA burst request
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x4 dout_oem1 (1-bit mode) */ SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // dout_oem1 (1-bit mode)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */ | SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) // dout_doutm1 (1-bit mode)
; ;
// clang-format on
const uint_fast8_t output_multiplexing_mode = const uint_fast8_t output_multiplexing_mode =
config->slice_mode_multislice ? 11 : 9; config->slice_mode_multislice ? 11 : 9;
/* SGPIO0 to SGPIO7 */ /* SGPIO0 to SGPIO7 */
for (uint_fast8_t i = 0; i < 8; i++) { for (uint_fast8_t i = 0; i < 8; i++) {
// SGPIO pin 0 outputs slice A bit "i". // SGPIO pin 0 outputs slice A bit "i".
SGPIO_OUT_MUX_CFG(i) = SGPIO_OUT_MUX_CFG(i) = SGPIO_OUT_MUX_CFG_P_OE_CFG(0)
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // 11 = dout_doutm8c (8-bit mode 8c) (multislice L0/7, N0/7)
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(output_multiplexing_mode) /* 11/0xB=dout_doutm8c (8-bit mode 8c)(multislice L0/7, N0/7), 9=dout_doutm8a (8-bit mode 8a)(A0/7,B0/7) */ // 9 = dout_doutm8a (8-bit mode 8a) (A0/7, B0/7)
; | SGPIO_OUT_MUX_CFG_P_OUT_CFG(output_multiplexing_mode);
} }
const uint_fast8_t slice_indices[] = { const uint_fast8_t slice_indices[] = {
@ -158,82 +179,82 @@ void sgpio_configure(
const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03; const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03;
const bool single_slice = !config->slice_mode_multislice; const bool single_slice = !config->slice_mode_multislice;
const uint_fast8_t slice_count = config->slice_mode_multislice ? 8 : 1; const uint_fast8_t slice_count = config->slice_mode_multislice ? 8 : 1;
const uint_fast8_t clk_capture_mode = (direction == SGPIO_DIRECTION_TX) ? 0 : 0;
// Also enable slice D for clkout to the SCTimer // Also enable slice D for clkout to the SCTimer
uint32_t slice_enable_mask = BIT3; uint32_t slice_enable_mask = BIT3;
/* Configure Slice A, I, E, J, C, K, F, L (sgpio_slice_mode_multislice mode) */ /* Configure Slice A, I, E, J, C, K, F, L (sgpio_slice_mode_multislice mode) */
for(uint_fast8_t i=0; i<slice_count; i++) for (uint_fast8_t i = 0; i < slice_count; i++) {
{
const uint_fast8_t slice_index = slice_indices[i]; const uint_fast8_t slice_index = slice_indices[i];
const bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX); /* Only for slice0/A and RX mode set input_slice to 1 */ /* Only for slice0/A and RX mode set input_slice to 1 */
const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3; /* 0x0=Self-loop(slice0/A RX mode), 0x3=8 slices */ const bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX);
const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1; /* 0x0=External data pin(slice0/A RX mode), 0x1=Concatenate data */ /* 0 = Self-loop (slice0/A RX mode), 3 = 8 slices */
const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3;
/* 0 = External data pin (slice0/A RX mode), 1 = Concatenate data */
const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1;
// clang-format off
SGPIO_MUX_CFG(slice_index) = SGPIO_MUX_CFG(slice_index) =
SGPIO_MUX_CFG_CONCAT_ORDER(concat_order) SGPIO_MUX_CFG_CONCAT_ORDER(concat_order)
| SGPIO_MUX_CFG_CONCAT_ENABLE(concat_enable) | SGPIO_MUX_CFG_CONCAT_ENABLE(concat_enable)
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) /* Select qualifier slice A(0x0) */ | SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) // Select qualifier slice A
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) /* Select qualifier pin SGPIO9(0x1) */ | SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) // Select qualifier pin SGPIO9
| SGPIO_MUX_CFG_QUALIFIER_MODE(3) /* External SGPIO */ | SGPIO_MUX_CFG_QUALIFIER_MODE(3) // External SGPIO
| SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) /* Select clock source slice D(0x0) */ | SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) // Select clock source slice D
| SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) /* Source Clock Pin 0x0 = SGPIO8 */ | SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) // Source clock pin = SGPIO8
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) /* External clock signal(pin) selected */ | SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) // External clock signal selected
; ;
SGPIO_SLICE_MUX_CFG(slice_index) = SGPIO_SLICE_MUX_CFG(slice_index) =
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) /* 0x0=Use normal qualifier. */ SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) // Use normal qualifier
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(3) /* 0x3=Shift 1 byte(8bits) per clock. */ | SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(3) // Shift 1 byte (8 bits) per clock
| SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) /* 0x0=Detect rising edge. (Condition for input bit match interrupt) */ | SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) // Detect rising edge
| SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) /* 0x0=Normal clock. */ | SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) // Normal clock
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) /* 0x1=Use external clock from a pin or other slice */ | SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) // Use external clock from a pin or other slice
| SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(clk_capture_mode) /* 0x0=Use rising clock edge, 0x1=Use falling clock edge */ | SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(0) // Use rising clock edge
| SGPIO_SLICE_MUX_CFG_MATCH_MODE(0) /* 0x0=Do not match data */ | SGPIO_SLICE_MUX_CFG_MATCH_MODE(0) // Do not match data
; ;
// clang-format on
SGPIO_PRESET(slice_index) = 0; // External clock, don't care SGPIO_PRESET(slice_index) = 0; // External clock, don't care
SGPIO_COUNT(slice_index) = 0; // External clock, don't care SGPIO_COUNT(slice_index) = 0; // External clock, don't care
SGPIO_POS(slice_index) = SGPIO_POS(slice_index) = SGPIO_POS_POS_RESET(pos) | SGPIO_POS_POS(pos);
SGPIO_POS_POS_RESET(pos)
| SGPIO_POS_POS(pos)
;
SGPIO_REG(slice_index) = 0x00000000; // Primary output data register SGPIO_REG(slice_index) = 0x00000000; // Primary output data register
SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register
// clang-format on
slice_enable_mask |= (1 << slice_index); slice_enable_mask |= (1 << slice_index);
} }
if (config->slice_mode_multislice == false) { if (config->slice_mode_multislice == false) {
// clang-format off
SGPIO_MUX_CFG(slice_gpdma) = SGPIO_MUX_CFG(slice_gpdma) =
SGPIO_MUX_CFG_CONCAT_ORDER(0) /* Self-loop */ SGPIO_MUX_CFG_CONCAT_ORDER(0) // Self-loop
| SGPIO_MUX_CFG_CONCAT_ENABLE(1) | SGPIO_MUX_CFG_CONCAT_ENABLE(1) // Concatenate data
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) /* Select qualifier slice A(0x0) */ | SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) // Select qualifier slice A
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) /* Select qualifier pin SGPIO9(0x1) */ | SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) // Select qualifier pin SGPIO9
| SGPIO_MUX_CFG_QUALIFIER_MODE(3) /* External SGPIO */ | SGPIO_MUX_CFG_QUALIFIER_MODE(3) // External SGPIO
| SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) /* Select clock source slice D(0x0) */ | SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) // Select clock source slice D
| SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) /* Source Clock Pin 0x0 = SGPIO8 */ | SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) // Source clock pin = SGPIO8
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) /* External clock signal(pin) selected */ | SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) // External clock signal selected
; ;
SGPIO_SLICE_MUX_CFG(slice_gpdma) = SGPIO_SLICE_MUX_CFG(slice_gpdma) =
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) /* 0x0=Use normal qualifier. */ SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) // Use normal qualifier
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(0) /* 0x0=Shift 1 bit per clock. */ | SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(0) // Shift 1 bit per clock
| SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) /* 0x0=Detect rising edge. (Condition for input bit match interrupt) */ | SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) // Detect rising edge
| SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) /* 0x0=Normal clock. */ | SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) // Normal clock
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) /* 0x1=Use external clock from a pin or other slice */ | SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) // Use external clock from a pin or other slice
| SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(clk_capture_mode) /* 0x0=Use rising clock edge, 0x1=Use falling clock edge */ | SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(0) // Use rising clock edge
| SGPIO_SLICE_MUX_CFG_MATCH_MODE(0) /* 0x0=Do not match data */ | SGPIO_SLICE_MUX_CFG_MATCH_MODE(0) // Do not match data
; ;
// clang-format on
SGPIO_PRESET(slice_gpdma) = 0; // External clock, don't care SGPIO_PRESET(slice_gpdma) = 0; // External clock, don't care
SGPIO_COUNT(slice_gpdma) = 0; // External clock, don't care SGPIO_COUNT(slice_gpdma) = 0; // External clock, don't care
SGPIO_POS(slice_gpdma) = SGPIO_POS(slice_gpdma) = SGPIO_POS_POS_RESET(0x1f) | SGPIO_POS_POS(0x1f);
SGPIO_POS_POS_RESET(0x1f) SGPIO_REG(slice_gpdma) =
| SGPIO_POS_POS(0x1f) 0x11111111; // Primary output data register, LSB -> out
; SGPIO_REG_SS(slice_gpdma) =
SGPIO_REG(slice_gpdma) = 0x11111111; // Primary output data register, LSB -> out 0x11111111; // Shadow output data register, LSB -> out1
SGPIO_REG_SS(slice_gpdma) = 0x11111111; // Shadow output data register, LSB -> out1
slice_enable_mask |= (1 << slice_gpdma); slice_enable_mask |= (1 << slice_gpdma);
} }
@ -242,24 +263,26 @@ void sgpio_configure(
SGPIO_CTRL_ENABLE = slice_enable_mask; SGPIO_CTRL_ENABLE = slice_enable_mask;
} }
void sgpio_cpld_stream_enable(sgpio_config_t* const config) { void sgpio_cpld_stream_enable(sgpio_config_t* const config)
{
(void) config; (void) config;
// Enable codec data stream. // Enable codec data stream.
SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */ SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */
} }
void sgpio_cpld_stream_disable(sgpio_config_t* const config) { void sgpio_cpld_stream_disable(sgpio_config_t* const config)
{
(void) config; (void) config;
// Disable codec data stream. // Disable codec data stream.
SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */ SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */
} }
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config) { bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config)
{
(void) config; (void) config;
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */ return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
} }
#ifdef RAD1O #ifdef RAD1O
/* The rad1o hardware has a bug which makes it /* The rad1o hardware has a bug which makes it
* necessary to also switch between the two options based * necessary to also switch between the two options based
@ -274,7 +297,8 @@ static bool sgpio_invert = false;
/* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert /* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert
* gets called. */ * gets called. */
static void update_q_invert(sgpio_config_t* const config) { static void update_q_invert(sgpio_config_t* const config)
{
/* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */ /* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */
bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0; bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0;
@ -290,7 +314,10 @@ static void update_q_invert(sgpio_config_t* const config) {
} }
} }
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) { void sgpio_cpld_stream_rx_set_q_invert(
sgpio_config_t* const config,
const uint_fast8_t invert)
{
if (invert) { if (invert) {
sgpio_invert = true; sgpio_invert = true;
} else { } else {
@ -301,7 +328,10 @@ void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_
} }
#else #else
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) { void sgpio_cpld_stream_rx_set_q_invert(
sgpio_config_t* const config,
const uint_fast8_t invert)
{
gpio_write(config->gpio_rx_q_invert, invert); gpio_write(config->gpio_rx_q_invert, invert);
} }
#endif #endif

View File

@ -42,18 +42,14 @@ typedef struct sgpio_config_t {
void sgpio_configure_pin_functions(sgpio_config_t* const config); void sgpio_configure_pin_functions(sgpio_config_t* const config);
void sgpio_test_interface(sgpio_config_t* const config); void sgpio_test_interface(sgpio_config_t* const config);
void sgpio_set_slice_mode( void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice);
sgpio_config_t* const config, void sgpio_configure(sgpio_config_t* const config, const sgpio_direction_t direction);
const bool multi_slice
);
void sgpio_configure(
sgpio_config_t* const config,
const sgpio_direction_t direction
);
void sgpio_cpld_stream_enable(sgpio_config_t* const config); void sgpio_cpld_stream_enable(sgpio_config_t* const config);
void sgpio_cpld_stream_disable(sgpio_config_t* const config); void sgpio_cpld_stream_disable(sgpio_config_t* const config);
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config); bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config);
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert); void sgpio_cpld_stream_rx_set_q_invert(
sgpio_config_t* const config,
const uint_fast8_t invert);
#endif //__SGPIO_H__ #endif //__SGPIO_H__

View File

@ -46,7 +46,10 @@ uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg)
* Write to one or more contiguous registers. data[0] should be the first * Write to one or more contiguous registers. data[0] should be the first
* register number, one or more values follow. * register number, one or more values follow.
*/ */
void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count) void si5351c_write(
si5351c_driver_t* const drv,
const uint8_t* const data,
const size_t data_count)
{ {
i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0);
} }
@ -68,16 +71,16 @@ void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv)
/* Power down all CLKx */ /* Power down all CLKx */
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv) void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
{ {
uint8_t data[] = { 16 uint8_t data[] = {
, SI5351C_CLK_POWERDOWN 16,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE,
}; SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
@ -135,9 +138,12 @@ void si5351c_reset_pll(si5351c_driver_t* const drv)
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
void si5351c_configure_multisynth(si5351c_driver_t* const drv, void si5351c_configure_multisynth(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number, const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3, const uint32_t p1,
const uint32_t p2,
const uint32_t p3,
const uint_fast8_t r_div) const uint_fast8_t r_div)
{ {
/* /*
@ -166,7 +172,9 @@ void si5351c_configure_multisynth(si5351c_driver_t* const drv,
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source) void si5351c_configure_clock_control(
si5351c_driver_t* const drv,
const enum pll_sources source)
{ {
uint8_t pll; uint8_t pll;
#ifdef RAD1O #ifdef RAD1O
@ -186,15 +194,29 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll
#endif #endif
/* Clock to CPU is deactivated as it is not used and creates noise */ /* Clock to CPU is deactivated as it is not used and creates noise */
/* External clock output is kept in current state */ /* External clock output is kept in current state */
uint8_t data[] = {16 uint8_t data[] = {
,SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) 16,
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
,clk3_ctrl SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA),
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV,
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA),
clk3_ctrl,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA),
SI5351C_CLK_POWERDOWN |
SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
,
SI5351C_CLK_POWERDOWN |
SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
}; };
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
@ -210,30 +232,31 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
/* 7: Clock to CPU is deactivated as it is not used and creates noise */ /* 7: Clock to CPU is deactivated as it is not used and creates noise */
/* 3: External clock output is deactivated by default */ /* 3: External clock output is deactivated by default */
// uint8_t data[] = { 3, ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5))}; // uint8_t data[] = { 3, ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5))};
uint8_t data[] = { SI5351C_REG_OUTPUT_EN, uint8_t data[] = {
SI5351C_CLK_ENABLE(0) | SI5351C_REG_OUTPUT_EN,
SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(2) |
SI5351C_CLK_ENABLE(2) | SI5351C_CLK_DISABLE(3) | SI5351C_CLK_ENABLE(4) |
SI5351C_CLK_DISABLE(3) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_ENABLE(4) | SI5351C_CLK_DISABLE(7)};
SI5351C_CLK_ENABLE(5) |
SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_DISABLE(7)
};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on){ void si5351c_set_int_mode(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint_fast8_t on)
{
uint8_t data[] = {16, 0}; uint8_t data[] = {16, 0};
if (ms_number < 8) { if (ms_number < 8) {
data[0] = 16 + ms_number; data[0] = 16 + ms_number;
data[1] = si5351c_read_single(drv, data[0]); data[1] = si5351c_read_single(drv, data[0]);
if(on) if (on) {
data[1] |= SI5351C_CLK_INT_MODE; data[1] |= SI5351C_CLK_INT_MODE;
else } else {
data[1] &= ~(SI5351C_CLK_INT_MODE); data[1] &= ~(SI5351C_CLK_INT_MODE);
}
si5351c_write(drv, data, 2); si5351c_write(drv, data, 2);
} }
@ -247,7 +270,8 @@ void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_source
} }
} }
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv) { bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv)
{
return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0; return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0;
} }
@ -256,10 +280,11 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
/* Set optput in output enable register */ /* Set optput in output enable register */
uint8_t output_enable = si5351c_read_single(drv, 3); uint8_t output_enable = si5351c_read_single(drv, 3);
output_enable = output_enable & !SI5351C_CLK_DISABLE(3); output_enable = output_enable & !SI5351C_CLK_DISABLE(3);
if(enable) if (enable) {
output_enable = output_enable | SI5351C_CLK_ENABLE(3); output_enable = output_enable | SI5351C_CLK_ENABLE(3);
else } else {
output_enable = output_enable | SI5351C_CLK_DISABLE(3); output_enable = output_enable | SI5351C_CLK_DISABLE(3);
}
uint8_t oe_data[] = {SI5351C_REG_OUTPUT_EN, output_enable}; uint8_t oe_data[] = {SI5351C_REG_OUTPUT_EN, output_enable};
si5351c_write(drv, oe_data, 2); si5351c_write(drv, oe_data, 2);
@ -282,10 +307,13 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
pll = SI5351C_CLK_PLL_SRC_A; pll = SI5351C_CLK_PLL_SRC_A;
} }
#endif #endif
if(enable) if (enable) {
clk3_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA); clk3_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
else SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
} else {
clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE; clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
}
uint8_t clk3_data[] = {SI5351C_REG_CLK3_CTRL, clk3_ctrl}; uint8_t clk3_data[] = {SI5351C_REG_CLK3_CTRL, clk3_ctrl};
si5351c_write(drv, clk3_data, 2); si5351c_write(drv, clk3_data, 2);
} }

View File

@ -24,8 +24,7 @@
#define __SI5351C_H #define __SI5351C_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -78,19 +77,30 @@ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv);
void si5351c_configure_pll_sources(si5351c_driver_t* const drv); void si5351c_configure_pll_sources(si5351c_driver_t* const drv);
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv); void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv);
void si5351c_reset_pll(si5351c_driver_t* const drv); void si5351c_reset_pll(si5351c_driver_t* const drv);
void si5351c_configure_multisynth(si5351c_driver_t* const drv, void si5351c_configure_multisynth(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number, const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3, const uint32_t p1,
const uint32_t p2,
const uint32_t p3,
const uint_fast8_t r_div); const uint_fast8_t r_div);
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source); void si5351c_configure_clock_control(
si5351c_driver_t* const drv,
const enum pll_sources source);
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv); void si5351c_enable_clock_outputs(si5351c_driver_t* const drv);
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on); void si5351c_set_int_mode(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint_fast8_t on);
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source); void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source);
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv); bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv);
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val);
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg); uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg);
void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count); void si5351c_write(
si5351c_driver_t* const drv,
const uint8_t* const data,
const size_t data_count);
void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable);
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -21,18 +21,25 @@
#include "spi_bus.h" #include "spi_bus.h"
void spi_bus_start(spi_bus_t* const bus, const void* const config) { void spi_bus_start(spi_bus_t* const bus, const void* const config)
{
bus->start(bus, config); bus->start(bus, config);
} }
void spi_bus_stop(spi_bus_t* const bus) { void spi_bus_stop(spi_bus_t* const bus)
{
bus->stop(bus); bus->stop(bus);
} }
void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count) { void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count)
{
bus->transfer(bus, data, count); bus->transfer(bus, data, count);
} }
void spi_bus_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count) { void spi_bus_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count)
{
bus->transfer_gather(bus, transfers, count); bus->transfer_gather(bus, transfers, count);
} }

View File

@ -38,12 +38,18 @@ struct spi_bus_t {
void (*start)(spi_bus_t* const bus, const void* const config); void (*start)(spi_bus_t* const bus, const void* const config);
void (*stop)(spi_bus_t* const bus); void (*stop)(spi_bus_t* const bus);
void (*transfer)(spi_bus_t* const bus, void* const data, const size_t count); void (*transfer)(spi_bus_t* const bus, void* const data, const size_t count);
void (*transfer_gather)(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); void (*transfer_gather)(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count);
}; };
void spi_bus_start(spi_bus_t* const bus, const void* const config); void spi_bus_start(spi_bus_t* const bus, const void* const config);
void spi_bus_stop(spi_bus_t* const bus); void spi_bus_stop(spi_bus_t* const bus);
void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count); void spi_bus_transfer(spi_bus_t* const bus, void* const data, const size_t count);
void spi_bus_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); void spi_bus_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count);
#endif /*__SPI_BUS_H__*/ #endif /*__SPI_BUS_H__*/

View File

@ -24,7 +24,8 @@
#include <libopencm3/lpc43xx/rgu.h> #include <libopencm3/lpc43xx/rgu.h>
#include <libopencm3/lpc43xx/ssp.h> #include <libopencm3/lpc43xx/ssp.h>
void spi_ssp_start(spi_bus_t* const bus, const void* const _config) { void spi_ssp_start(spi_bus_t* const bus, const void* const _config)
{
const ssp_config_t* const config = _config; const ssp_config_t* const config = _config;
if (bus->obj == (void*) SSP0_BASE) { if (bus->obj == (void*) SSP0_BASE) {
@ -37,39 +38,36 @@ void spi_ssp_start(spi_bus_t* const bus, const void* const _config) {
SSP_CR1(bus->obj) = 0; SSP_CR1(bus->obj) = 0;
SSP_CPSR(bus->obj) = config->clock_prescale_rate; SSP_CPSR(bus->obj) = config->clock_prescale_rate;
SSP_CR0(bus->obj) = SSP_CR0(bus->obj) = (config->serial_clock_rate << 8) | SSP_CPOL_0_CPHA_0 |
(config->serial_clock_rate << 8) SSP_FRAME_SPI | config->data_bits;
| SSP_CPOL_0_CPHA_0
| SSP_FRAME_SPI
| config->data_bits
;
SSP_CR1(bus->obj) = SSP_CR1(bus->obj) =
SSP_SLAVE_OUT_ENABLE SSP_SLAVE_OUT_ENABLE | SSP_MASTER | SSP_ENABLE | SSP_MODE_NORMAL;
| SSP_MASTER
| SSP_ENABLE
| SSP_MODE_NORMAL
;
bus->config = config; bus->config = config;
} }
void spi_ssp_stop(spi_bus_t* const bus) { void spi_ssp_stop(spi_bus_t* const bus)
{
SSP_CR1(bus->obj) = 0; SSP_CR1(bus->obj) = 0;
} }
static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus) { static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus)
while( (SSP_SR(bus->obj) & SSP_SR_TNF) == 0 ); {
while ((SSP_SR(bus->obj) & SSP_SR_TNF) == 0) {}
} }
static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus) { static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus)
while( (SSP_SR(bus->obj) & SSP_SR_RNE) == 0 ); {
while ((SSP_SR(bus->obj) & SSP_SR_RNE) == 0) {}
} }
static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus) { static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus)
while( SSP_SR(bus->obj) & SSP_SR_BSY ); {
while (SSP_SR(bus->obj) & SSP_SR_BSY) {}
} }
static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data) { static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data)
{
spi_ssp_wait_for_tx_fifo_not_full(bus); spi_ssp_wait_for_tx_fifo_not_full(bus);
SSP_DR(bus->obj) = data; SSP_DR(bus->obj) = data;
spi_ssp_wait_for_not_busy(bus); spi_ssp_wait_for_not_busy(bus);
@ -77,7 +75,11 @@ static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data)
return SSP_DR(bus->obj); return SSP_DR(bus->obj);
} }
void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count) { void spi_ssp_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count)
{
const ssp_config_t* const config = bus->config; const ssp_config_t* const config = bus->config;
const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS; const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS;
@ -101,7 +103,8 @@ void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const t
gpio_set(config->gpio_select); gpio_set(config->gpio_select);
} }
void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count) { void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count)
{
const spi_transfer_t transfers[] = { const spi_transfer_t transfers[] = {
{data, count}, {data, count},
}; };

View File

@ -41,6 +41,9 @@ typedef struct ssp_config_t {
void spi_ssp_start(spi_bus_t* const bus, const void* const config); void spi_ssp_start(spi_bus_t* const bus, const void* const config);
void spi_ssp_stop(spi_bus_t* const bus); void spi_ssp_stop(spi_bus_t* const bus);
void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count); void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count);
void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); void spi_ssp_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count);
#endif /*__SPI_SSP_H__*/ #endif /*__SPI_SSP_H__*/

View File

@ -25,12 +25,14 @@
#include <libopencm3/lpc43xx/m4/nvic.h> #include <libopencm3/lpc43xx/m4/nvic.h>
#include <libopencm3/lpc43xx/sgpio.h> #include <libopencm3/lpc43xx/sgpio.h>
void baseband_streaming_enable(sgpio_config_t* const sgpio_config) { void baseband_streaming_enable(sgpio_config_t* const sgpio_config)
{
SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A); SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A);
sgpio_cpld_stream_enable(sgpio_config); sgpio_cpld_stream_enable(sgpio_config);
} }
void baseband_streaming_disable(sgpio_config_t* const sgpio_config) { void baseband_streaming_disable(sgpio_config_t* const sgpio_config)
{
sgpio_cpld_stream_disable(sgpio_config); sgpio_cpld_stream_disable(sgpio_config);
} }

View File

@ -49,6 +49,7 @@
static uint32_t max2837_freq_nominal_hz = 2560000000; static uint32_t max2837_freq_nominal_hz = 2560000000;
uint64_t freq_cache = 100000000; uint64_t freq_cache = 100000000;
/* /*
* Set freq/tuning between 0MHz to 7250 MHz (less than 16bits really used) * Set freq/tuning between 0MHz to 7250 MHz (less than 16bits really used)
* hz between 0 to 999999 Hz (not checked) * hz between 0 to 999999 Hz (not checked)
@ -68,8 +69,7 @@ bool set_freq(const uint64_t freq)
const max2837_mode_t prior_max2837_mode = max2837_mode(&max2837); const max2837_mode_t prior_max2837_mode = max2837_mode(&max2837);
max2837_set_mode(&max2837, MAX2837_MODE_STANDBY); max2837_set_mode(&max2837, MAX2837_MODE_STANDBY);
if(freq_mhz < MAX_LP_FREQ_MHZ) if (freq_mhz < MAX_LP_FREQ_MHZ) {
{
rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS); rf_path_set_filter(&rf_path, RF_PATH_FILTER_LOW_PASS);
#ifdef RAD1O #ifdef RAD1O
max2837_freq_nominal_hz = 2300000000; max2837_freq_nominal_hz = 2300000000;
@ -82,18 +82,17 @@ bool set_freq(const uint64_t freq)
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
max2837_set_frequency(&max2837, real_mixer_freq_hz - freq); max2837_set_frequency(&max2837, real_mixer_freq_hz - freq);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1); sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 1);
}else if( (freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ) ) } else if ((freq_mhz >= MIN_BYPASS_FREQ_MHZ) && (freq_mhz < MAX_BYPASS_FREQ_MHZ)) {
{
rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS); rf_path_set_filter(&rf_path, RF_PATH_FILTER_BYPASS);
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz; MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
/* mixer_freq_mhz <= not used in Bypass mode */ /* mixer_freq_mhz <= not used in Bypass mode */
max2837_set_frequency(&max2837, MAX2837_freq_hz); max2837_set_frequency(&max2837, MAX2837_freq_hz);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}else if( (freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ) ) } else if ((freq_mhz >= MIN_HP_FREQ_MHZ) && (freq_mhz <= MAX_HP_FREQ_MHZ)) {
{
if (freq_mhz < MID1_HP_FREQ_MHZ) { if (freq_mhz < MID1_HP_FREQ_MHZ) {
/* IF is graduated from 2150 MHz to 2750 MHz */ /* IF is graduated from 2150 MHz to 2750 MHz */
max2837_freq_nominal_hz = 2150000000 + (((freq - 2750000000) * 60) / 85); max2837_freq_nominal_hz =
2150000000 + (((freq - 2750000000) * 60) / 85);
} else if (freq_mhz < MID2_HP_FREQ_MHZ) { } else if (freq_mhz < MID2_HP_FREQ_MHZ) {
/* IF is graduated from 2350 MHz to 2650 MHz */ /* IF is graduated from 2350 MHz to 2650 MHz */
max2837_freq_nominal_hz = 2350000000 + ((freq - 3600000000) / 5); max2837_freq_nominal_hz = 2350000000 + ((freq - 3600000000) / 5);
@ -107,8 +106,7 @@ bool set_freq(const uint64_t freq)
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz); real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
max2837_set_frequency(&max2837, freq - real_mixer_freq_hz); max2837_set_frequency(&max2837, freq - real_mixer_freq_hz);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0); sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}else } else {
{
/* Error freq_mhz too high */ /* Error freq_mhz too high */
success = false; success = false;
} }
@ -123,11 +121,13 @@ bool set_freq(const uint64_t freq)
return success; return success;
} }
bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz, bool set_freq_explicit(
const uint64_t if_freq_hz,
const uint64_t lo_freq_hz,
const rf_path_filter_t path) const rf_path_filter_t path)
{ {
if ((if_freq_hz < ((uint64_t)MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ)) if ((if_freq_hz < ((uint64_t) MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ)) ||
|| (if_freq_hz > ((uint64_t)MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))) { (if_freq_hz > ((uint64_t) MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))) {
return false; return false;
} }

View File

@ -29,7 +29,9 @@
#include <stdbool.h> #include <stdbool.h>
bool set_freq(const uint64_t freq); bool set_freq(const uint64_t freq);
bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz, bool set_freq_explicit(
const uint64_t if_freq_hz,
const uint64_t lo_freq_hz,
const rf_path_filter_t path); const rf_path_filter_t path);
#endif /*__TUNING_H__*/ #endif /*__TUNING_H__*/

View File

@ -26,265 +26,336 @@
/* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */ /* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */
static const uint8_t font_fixed_8x16_glyph_data[] = { static const uint8_t font_fixed_8x16_glyph_data[] = {
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, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0xff, 0x24, 0x24, 0xff, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
0x00, 0x00, 0x10, 0x78, 0x14, 0x14, 0x14, 0x18, 0x30, 0x50, 0x50, 0x50, 0x3c, 0x10, 0x00, 0x00, 0x48, 0x48, 0xff, 0x24, 0x24, 0xff, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x46, 0x29, 0x29, 0x19, 0x16, 0x68, 0x98, 0x94, 0x94, 0x62, 0x00, 0x00, 0x00, 0x00, 0x10, 0x78, 0x14, 0x14, 0x14, 0x18, 0x30, 0x50, 0x50, 0x50, 0x3c, 0x10,
0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x14, 0x88, 0x54, 0x72, 0x22, 0x62, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x29, 0x29, 0x19, 0x16, 0x68, 0x98, 0x94,
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x14, 0x88,
0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40, 0x00, 0x54, 0x72, 0x22, 0x62, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x40,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x5a, 0x5a, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10,
0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x10, 0x0c, 0x10, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x00, 0x00, 0x00, 0x30, 0x30, 0x28, 0x28, 0x24, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x24, 0x42, 0x42, 0x5a, 0x5a, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x04, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08, 0x04,
0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x02, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x10, 0x0c,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x10, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
0x00, 0x00, 0x00, 0x1c, 0x22, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00, 0x28, 0x28, 0x24, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x04, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x44,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x04, 0x18, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x20, 0x10, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x30, 0x40, 0x30, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x30, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x59, 0x55, 0x55, 0x55, 0x39, 0x01, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08,
0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x14, 0x14, 0x22, 0x3e, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20,
0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00, 0x00, 0x18, 0x04, 0x18, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x30, 0x40, 0x30, 0x08, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x30, 0x08, 0x08, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x72, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x59, 0x55,
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x55, 0x55, 0x39, 0x01, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14,
0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x14, 0x14, 0x14, 0x22, 0x3e, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x82, 0x42, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x44,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x42, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x42, 0x66, 0x66, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02,
0x00, 0x00, 0x00, 0x42, 0x46, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x42, 0x00, 0x00, 0x00, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x72, 0x42, 0x42, 0x44, 0x38,
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42,
0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x0c, 0x30, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x42, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x82, 0x00,
0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x66, 0x5a, 0x5a,
0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22, 0x41, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x46,
0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x02, 0x02,
0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, 0x42, 0x42, 0x24, 0x18, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42,
0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x3e, 0x12, 0x22, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3c, 0x42, 0x02, 0x02, 0x0c, 0x30, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x7c, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x1a, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x00, 0x00, 0x00, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x02, 0x02, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00, 0x22, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, 0x00, 0x41, 0x41, 0x49, 0x49, 0x55, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x7e, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22, 0x41, 0x00,
0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x7e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x22, 0x22, 0x22, 0x1c, 0x02, 0x3e, 0x42, 0x42, 0x3c, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x10,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x08, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, 0x08, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x7c, 0x42, 0x62, 0x5c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x1a, 0x26, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x42, 0x26, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x02, 0x02, 0x3c, 0x40, 0x40, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, 0x00, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x7e, 0x02, 0x04, 0x78, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x36, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x7e, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x49, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x22,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18, 0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x22, 0x22, 0x1c, 0x02, 0x3e, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x08, 0x04, 0x03, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10,
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x22, 0x12, 0x0a,
0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; 0x00, 0x00, 0x00, 0x37, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x42,
0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a,
0x26, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x40, 0x40, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x02, 0x02, 0x3c, 0x40,
0x40, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x3c, 0x08,
0x08, 0x08, 0x08, 0x08, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x36, 0x14, 0x14, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x49, 0x55, 0x55, 0x22,
0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x24, 0x18,
0x18, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x41, 0x22, 0x22, 0x14, 0x14, 0x14, 0x08, 0x08, 0x04, 0x03, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x20, 0x10, 0x08, 0x08, 0x04, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x08, 0x08, 0x08, 0x08, 0x04, 0x08, 0x08, 0x08, 0x08,
0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x10,
0x10, 0x20, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x8e, 0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const ui_font_t font_fixed_8x16 = { static const ui_font_t font_fixed_8x16 =
{ 8, 16 }, {{8, 16}, font_fixed_8x16_glyph_data, 0x20, 95, (8 * 16 + 7U) >> 3};
font_fixed_8x16_glyph_data,
0x20, 95,
(8 * 16 + 7U) >> 3
};
static const uint8_t font_fixed_24x19_glyph_data[] = { static const uint8_t font_fixed_24x19_glyph_data[] = {
0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c,
0x00, 0x78, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x77, 0x00, 0xc0, 0x73, 0x00, 0xc0, 0x71, 0x00, 0xc0, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00,
0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3c, 0x00, 0xfc, 0x1f, 0xe0, 0xff, 0x1f, 0xf8, 0xff, 0x07, 0xfc, 0x07, 0x00, 0x3c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38,
0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x3f, 0x3c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0xfe, 0x3f, 0x00, 0xfe, 0x1f, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x38, 0xf8, 0xff, 0x3f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8,
0x00, 0x80, 0x0f, 0x00, 0xc0, 0x0f, 0x00, 0xe0, 0x0f, 0x00, 0xf8, 0x0f, 0x00, 0x7c, 0x0f, 0x00, 0x1e, 0x0f, 0x00, 0x0f, 0x0f, 0xc0, 0x07, 0x0f, 0xe0, 0x01, 0x0f, 0xf0, 0x00, 0x0f, 0x7c, 0x00, 0x0f, 0x1e, 0x00, 0x0f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x00, 0x78, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x7e,
0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xdc, 0xff, 0x07, 0xfc, 0xff, 0x1f, 0xfc, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x7f, 0x00, 0x80, 0x77, 0x00, 0xc0, 0x73, 0x00, 0xc0, 0x71, 0x00,
0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x00, 0xdc, 0xff, 0x07, 0xfc, 0xff, 0x1f, 0xfc, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xc0, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00,
0xfc, 0xff, 0x7f, 0xfc, 0xff, 0x7f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x03, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70,
0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0xe0, 0xff, 0x07,
0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x3f, 0xf8, 0xff, 0x3f, 0xe0, 0xff, 0x3b, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c,
0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3c, 0x00, 0xfc,
0x1f, 0xe0, 0xff, 0x1f, 0xf8, 0xff, 0x07, 0xfc, 0x07, 0x00, 0x3c, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x1c, 0x00, 0x00, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xfc,
0xff, 0x3f, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x3f, 0x3c, 0x00,
0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38,
0x00, 0xfe, 0x3f, 0x00, 0xfe, 0x1f, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0x38, 0x00,
0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x38, 0xf8, 0xff,
0x3f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0x00, 0x80, 0x0f, 0x00, 0xc0, 0x0f,
0x00, 0xe0, 0x0f, 0x00, 0xf8, 0x0f, 0x00, 0x7c, 0x0f, 0x00, 0x1e, 0x0f, 0x00,
0x0f, 0x0f, 0xc0, 0x07, 0x0f, 0xe0, 0x01, 0x0f, 0xf0, 0x00, 0x0f, 0x7c, 0x00,
0x0f, 0x1e, 0x00, 0x0f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f, 0xfe, 0xff, 0x7f,
0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x0f, 0xfc,
0xff, 0x3f, 0xfc, 0xff, 0x3f, 0xfc, 0xff, 0x3f, 0x1c, 0x00, 0x00, 0x1c, 0x00,
0x00, 0x1c, 0x00, 0x00, 0xdc, 0xff, 0x07, 0xfc, 0xff, 0x1f, 0xfc, 0xff, 0x1f,
0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x1c,
0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff,
0x1f, 0xe0, 0xff, 0x07, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f,
0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x00, 0xdc,
0xff, 0x07, 0xfc, 0xff, 0x1f, 0xfc, 0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00,
0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c,
0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xfc, 0xff, 0x7f, 0xfc,
0xff, 0x7f, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x03, 0x00, 0xe0, 0x01,
0x00, 0xf0, 0x01, 0x00, 0xf0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3c, 0x00, 0x00,
0x1e, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x0f, 0x00, 0x80, 0x07, 0x00, 0xc0, 0x03,
0x00, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x3c,
0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8,
0xff, 0x1f, 0xf0, 0xff, 0x0f, 0xf8, 0xff, 0x1f, 0x3c, 0x00, 0x38, 0x1c, 0x00,
0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x1f,
0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xe0, 0xff, 0x07, 0xf8, 0xff, 0x1f, 0xf8,
0xff, 0x1f, 0x3c, 0x00, 0x3c, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00,
0x38, 0x1c, 0x00, 0x38, 0x3c, 0x00, 0x3c, 0xf8, 0xff, 0x3f, 0xf8, 0xff, 0x3f,
0xe0, 0xff, 0x3b, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x1c, 0x00, 0x38, 0x3c,
0x00, 0x3c, 0xf8, 0xff, 0x1f, 0xf8, 0xff, 0x1f, 0xe0, 0xff, 0x07,
}; };
static const ui_font_t font_fixed_24x19 = { static const ui_font_t font_fixed_24x19 =
{ 24, 19 }, {{24, 19}, font_fixed_24x19_glyph_data, 0x30, 10, (24 * 19 + 7U) >> 3};
font_fixed_24x19_glyph_data,
0x30, 10,
(24 * 19 + 7U) >> 3
};
static const uint8_t font_fixed_16x14_glyph_data[] = { static const uint8_t font_fixed_16x14_glyph_data[] = {
0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06,
0x00, 0x03, 0x80, 0x03, 0xc0, 0x03, 0xe0, 0x03, 0x70, 0x03, 0x20, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f,
0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x00, 0x60, 0x00, 0x70, 0x80, 0x3f, 0xf8, 0x1f, 0xfc, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x06, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0x1f, 0x00, 0x03, 0x80, 0x03, 0xc0, 0x03, 0xe0, 0x03, 0x70, 0x03, 0x20,
0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x00, 0x60, 0x00, 0x60, 0xc0, 0x3f, 0xc0, 0x7f, 0x00, 0x60, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03,
0x00, 0x1c, 0x00, 0x1e, 0x00, 0x1f, 0x80, 0x1b, 0xc0, 0x19, 0xe0, 0x18, 0x70, 0x18, 0x38, 0x18, 0x1c, 0x18, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x03, 0x00, 0x03, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x00,
0xfe, 0x7f, 0xfe, 0x7f, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x1f, 0xfe, 0x3f, 0x0e, 0x70, 0x00, 0x60, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x60, 0x00, 0x70, 0x80, 0x3f, 0xf8, 0x1f, 0xfc, 0x00, 0x0e, 0x00, 0x06, 0x00,
0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x00, 0xf6, 0x1f, 0xfe, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x06, 0x00, 0xfe, 0x7f, 0xfe, 0x7f, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06,
0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x70, 0x00, 0x30, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x80, 0x03, 0x80, 0x01, 0xc0, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0xc0, 0x3f, 0xc0, 0x7f, 0x00, 0x60, 0x00, 0x60,
0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x00, 0x1c, 0x00, 0x1e, 0x00,
0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x7f, 0xf8, 0x6f, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0x1f, 0x80, 0x1b, 0xc0, 0x19, 0xe0, 0x18, 0x70, 0x18, 0x38, 0x18, 0x1c, 0x18,
0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0xfe, 0x7f, 0xfe,
0x7f, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xf6, 0x1f, 0xfe, 0x3f, 0x0e, 0x70,
0x00, 0x60, 0x00, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8,
0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x00, 0xf6, 0x1f, 0xfe, 0x3f,
0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8,
0x1f, 0xfe, 0x7f, 0xfe, 0x7f, 0x00, 0x70, 0x00, 0x30, 0x00, 0x18, 0x00, 0x1c,
0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x80, 0x03, 0x80, 0x01, 0xc0, 0x00, 0xe0,
0x00, 0x60, 0x00, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60,
0x0e, 0x70, 0xfc, 0x3f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60, 0x06, 0x60, 0x0e,
0x70, 0xfc, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xfc, 0x3f, 0x0e, 0x70, 0x06, 0x60,
0x06, 0x60, 0x06, 0x60, 0x0e, 0x70, 0xfc, 0x7f, 0xf8, 0x6f, 0x00, 0x60, 0x06,
0x60, 0x0e, 0x70, 0xfc, 0x3f, 0xf8, 0x1f,
}; };
static const ui_font_t font_fixed_16x14 = { static const ui_font_t font_fixed_16x14 =
{ 16, 14 }, {{16, 14}, font_fixed_16x14_glyph_data, 0x30, 10, (16 * 14 + 7U) >> 3};
font_fixed_16x14_glyph_data,
0x30, 10,
(16 * 14 + 7U) >> 3
};
static const uint8_t bitmap_amp_rx_data[] = { static const uint8_t bitmap_amp_rx_data[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x0c, 0x00, 0x30, 0x0c, 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x30, 0x00, 0x0c, 0x30, 0x00, 0x0c, 0x60, 0x00, 0x06, 0x60, 0x00, 0x06, 0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x80, 0x81, 0x01, 0x80, 0x81, 0x01, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60,
}; 0x0c, 0x00, 0x30, 0x0c, 0x00, 0x30, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18,
0x30, 0x00, 0x0c, 0x30, 0x00, 0x0c, 0x60, 0x00, 0x06, 0x60, 0x00, 0x06,
0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x80, 0x81, 0x01, 0x80, 0x81, 0x01,
0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00,
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00};
static const ui_bitmap_t bitmap_amp_rx = { static const ui_bitmap_t bitmap_amp_rx = {{24, 24}, bitmap_amp_rx_data};
{ 24, 24 }, bitmap_amp_rx_data
};
static const uint8_t bitmap_amp_tx_data[] = { static const uint8_t bitmap_amp_tx_data[] = {
0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00, 0x80, 0x81, 0x01, 0x80, 0x81, 0x01, 0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03, 0x60, 0x00, 0x06, 0x60, 0x00, 0x06, 0x30, 0x00, 0x0c, 0x30, 0x00, 0x0c, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x0c, 0x00, 0x30, 0x0c, 0x00, 0x30, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
}; 0x00, 0x66, 0x00, 0x00, 0x66, 0x00, 0x00, 0xc3, 0x00, 0x00, 0xc3, 0x00,
0x80, 0x81, 0x01, 0x80, 0x81, 0x01, 0xc0, 0x00, 0x03, 0xc0, 0x00, 0x03,
0x60, 0x00, 0x06, 0x60, 0x00, 0x06, 0x30, 0x00, 0x0c, 0x30, 0x00, 0x0c,
0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x0c, 0x00, 0x30, 0x0c, 0x00, 0x30,
0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const ui_bitmap_t bitmap_amp_tx = { static const ui_bitmap_t bitmap_amp_tx = {{24, 24}, bitmap_amp_tx_data};
{ 24, 24 }, bitmap_amp_tx_data
};
static const uint8_t bitmap_antenna_data[] = { static const uint8_t bitmap_antenna_data[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x18, 0x60, 0x06, 0x18, 0x60, 0x0c, 0x18, 0x30, 0x0c, 0x18, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x18, 0x0c, 0x30, 0x18, 0x0c, 0x60, 0x18, 0x06, 0x60, 0x18, 0x06, 0xc0, 0x18, 0x03, 0xc0, 0x18, 0x03, 0x80, 0x99, 0x01, 0x80, 0x99, 0x01, 0x00, 0xdb, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x06, 0x18, 0x60, 0x06, 0x18, 0x60,
}; 0x0c, 0x18, 0x30, 0x0c, 0x18, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x30, 0x18, 0x0c, 0x30, 0x18, 0x0c, 0x60, 0x18, 0x06, 0x60, 0x18, 0x06,
0xc0, 0x18, 0x03, 0xc0, 0x18, 0x03, 0x80, 0x99, 0x01, 0x80, 0x99, 0x01,
0x00, 0xdb, 0x00, 0x00, 0xdb, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00};
static const ui_bitmap_t bitmap_antenna = { static const ui_bitmap_t bitmap_antenna = {{24, 24}, bitmap_antenna_data};
{ 24, 24 }, bitmap_antenna_data
};
static const uint8_t bitmap_filter_hp_data[] = { static const uint8_t bitmap_filter_hp_data[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0xf8, 0xc7, 0x03, 0xfc, 0xc7, 0x03, 0x0e, 0xc0, 0x03, 0x06, 0xc0, 0x03, 0x03, 0xc0, 0x03, 0x03, 0xc0, 0x83, 0x01, 0xc0, 0x83, 0x01, 0xc0, 0xc3, 0x00, 0xc0, 0xc3, 0x00, 0xc0, 0x63, 0x00, 0xc0, 0x63, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0,
}; 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0xf8, 0xc7, 0x03, 0xfc, 0xc7,
0x03, 0x0e, 0xc0, 0x03, 0x06, 0xc0, 0x03, 0x03, 0xc0, 0x03, 0x03, 0xc0,
0x83, 0x01, 0xc0, 0x83, 0x01, 0xc0, 0xc3, 0x00, 0xc0, 0xc3, 0x00, 0xc0,
0x63, 0x00, 0xc0, 0x63, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0,
0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const ui_bitmap_t bitmap_filter_hp = { static const ui_bitmap_t bitmap_filter_hp = {{24, 24}, bitmap_filter_hp_data};
{ 24, 24 }, bitmap_filter_hp_data
};
static const uint8_t bitmap_filter_lp_data[] = { static const uint8_t bitmap_filter_lp_data[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xe3, 0x1f, 0xc0, 0xe3, 0x3f, 0xc0, 0x03, 0x70, 0xc0, 0x03, 0x60, 0xc0, 0x03, 0xc0, 0xc0, 0x03, 0xc0, 0xc0, 0x03, 0x80, 0xc1, 0x03, 0x80, 0xc1, 0x03, 0x00, 0xc3, 0x03, 0x00, 0xc3, 0x03, 0x00, 0xc6, 0x03, 0x00, 0xc6, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0,
}; 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xe3, 0x1f, 0xc0, 0xe3, 0x3f, 0xc0,
0x03, 0x70, 0xc0, 0x03, 0x60, 0xc0, 0x03, 0xc0, 0xc0, 0x03, 0xc0, 0xc0,
0x03, 0x80, 0xc1, 0x03, 0x80, 0xc1, 0x03, 0x00, 0xc3, 0x03, 0x00, 0xc3,
0x03, 0x00, 0xc6, 0x03, 0x00, 0xc6, 0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0,
0x03, 0x00, 0xc0, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
static const ui_bitmap_t bitmap_filter_lp = { static const ui_bitmap_t bitmap_filter_lp = {{24, 24}, bitmap_filter_lp_data};
{ 24, 24 }, bitmap_filter_lp_data
};
static const uint8_t bitmap_mixer_data[] = { static const uint8_t bitmap_mixer_data[] = {
0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e, 0x38, 0x00, 0x1c, 0x7c, 0x00, 0x3e, 0xee, 0x00, 0x77, 0xc6, 0x81, 0x63, 0x86, 0xc3, 0x61, 0x03, 0xe7, 0xc0, 0x03, 0x7e, 0xc0, 0x03, 0x3c, 0xc0, 0x03, 0x3c, 0xc0, 0x03, 0x7e, 0xc0, 0x03, 0xe7, 0xc0, 0x86, 0xc3, 0x61, 0xc6, 0x81, 0x63, 0xee, 0x00, 0x77, 0x7c, 0x00, 0x3e, 0x38, 0x00, 0x1c, 0x70, 0x00, 0x0e, 0xe0, 0x81, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e,
}; 0x38, 0x00, 0x1c, 0x7c, 0x00, 0x3e, 0xee, 0x00, 0x77, 0xc6, 0x81, 0x63,
0x86, 0xc3, 0x61, 0x03, 0xe7, 0xc0, 0x03, 0x7e, 0xc0, 0x03, 0x3c, 0xc0,
0x03, 0x3c, 0xc0, 0x03, 0x7e, 0xc0, 0x03, 0xe7, 0xc0, 0x86, 0xc3, 0x61,
0xc6, 0x81, 0x63, 0xee, 0x00, 0x77, 0x7c, 0x00, 0x3e, 0x38, 0x00, 0x1c,
0x70, 0x00, 0x0e, 0xe0, 0x81, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00};
static const ui_bitmap_t bitmap_mixer = { static const ui_bitmap_t bitmap_mixer = {{24, 24}, bitmap_mixer_data};
{ 24, 24 }, bitmap_mixer_data
};
static const uint8_t bitmap_oscillator_data[] = { static const uint8_t bitmap_oscillator_data[] = {
0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e, 0x38, 0x00, 0x1c, 0x1c, 0x00, 0x38, 0x0e, 0x03, 0x70, 0x86, 0x07, 0x60, 0xc6, 0x0f, 0x60, 0xc3, 0x0c, 0xc0, 0xe3, 0x1c, 0xc0, 0x63, 0x18, 0xc6, 0x63, 0x18, 0xc6, 0x03, 0x38, 0xc7, 0x03, 0x30, 0xc3, 0x06, 0xf0, 0x63, 0x06, 0xe0, 0x61, 0x0e, 0xc0, 0x70, 0x1c, 0x00, 0x38, 0x38, 0x00, 0x1c, 0x70, 0x00, 0x0e, 0xe0, 0x81, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00 0x00, 0x7e, 0x00, 0xc0, 0xff, 0x03, 0xe0, 0x81, 0x07, 0x70, 0x00, 0x0e,
}; 0x38, 0x00, 0x1c, 0x1c, 0x00, 0x38, 0x0e, 0x03, 0x70, 0x86, 0x07, 0x60,
0xc6, 0x0f, 0x60, 0xc3, 0x0c, 0xc0, 0xe3, 0x1c, 0xc0, 0x63, 0x18, 0xc6,
0x63, 0x18, 0xc6, 0x03, 0x38, 0xc7, 0x03, 0x30, 0xc3, 0x06, 0xf0, 0x63,
0x06, 0xe0, 0x61, 0x0e, 0xc0, 0x70, 0x1c, 0x00, 0x38, 0x38, 0x00, 0x1c,
0x70, 0x00, 0x0e, 0xe0, 0x81, 0x07, 0xc0, 0xff, 0x03, 0x00, 0x7e, 0x00};
static const ui_bitmap_t bitmap_oscillator = { static const ui_bitmap_t bitmap_oscillator = {{24, 24}, bitmap_oscillator_data};
{ 24, 24 }, bitmap_oscillator_data
};
static const uint8_t bitmap_wire_8_data[] = { static const uint8_t bitmap_wire_8_data[] = {0xff, 0xff};
0xff, 0xff
};
static const ui_bitmap_t bitmap_wire_8 = { static const ui_bitmap_t bitmap_wire_8 = {{2, 8}, bitmap_wire_8_data};
{ 2, 8 }, bitmap_wire_8_data
};
static const uint8_t bitmap_wire_24_data[] = { static const uint8_t bitmap_wire_24_data[] = {
0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00,
}; 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00,
0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00,
0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00,
0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00,
0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00};
static const ui_bitmap_t bitmap_wire_24 = { static const ui_bitmap_t bitmap_wire_24 = {{24, 24}, bitmap_wire_24_data};
{ 24, 24 }, bitmap_wire_24_data
};
static const uint8_t bitmap_blank_24_data[] = { static const uint8_t bitmap_blank_24_data[] = {
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, 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,
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};
static const ui_bitmap_t bitmap_blank_24 = { static const ui_bitmap_t bitmap_blank_24 = {{24, 24}, bitmap_blank_24_data};
{ 24, 24 }, bitmap_blank_24_data
};
static const uint8_t bitmap_waves_rx_data[] = { static const uint8_t bitmap_waves_rx_data[] = {
0xc0, 0x00, 0x60, 0x00, 0x70, 0x06, 0x30, 0x07, 0x38, 0x03, 0x98, 0x33, 0x98, 0x39, 0x98, 0x19, 0xcc, 0x18, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x18, 0x98, 0x19, 0x98, 0x39, 0x98, 0x33, 0x38, 0x03, 0x30, 0x07, 0x70, 0x06, 0x60, 0x00, 0xc0, 0x00 0xc0, 0x00, 0x60, 0x00, 0x70, 0x06, 0x30, 0x07, 0x38, 0x03, 0x98, 0x33,
}; 0x98, 0x39, 0x98, 0x19, 0xcc, 0x18, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c,
0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xcc, 0x18, 0x98, 0x19, 0x98, 0x39,
0x98, 0x33, 0x38, 0x03, 0x30, 0x07, 0x70, 0x06, 0x60, 0x00, 0xc0, 0x00};
static const ui_bitmap_t bitmap_waves_rx = { static const ui_bitmap_t bitmap_waves_rx = {{16, 24}, bitmap_waves_rx_data};
{ 16, 24 }, bitmap_waves_rx_data
};
static const uint8_t bitmap_waves_tx_data[] = { static const uint8_t bitmap_waves_tx_data[] = {
0x00, 0x03, 0x00, 0x06, 0x60, 0x0e, 0xe0, 0x0c, 0xc0, 0x1c, 0xcc, 0x19, 0x9c, 0x19, 0x98, 0x19, 0x18, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x18, 0x33, 0x98, 0x19, 0x9c, 0x19, 0xcc, 0x19, 0xc0, 0x1c, 0xe0, 0x0c, 0x60, 0x0e, 0x00, 0x06, 0x00, 0x03 0x00, 0x03, 0x00, 0x06, 0x60, 0x0e, 0xe0, 0x0c, 0xc0, 0x1c, 0xcc, 0x19,
}; 0x9c, 0x19, 0x98, 0x19, 0x18, 0x33, 0x30, 0x33, 0x30, 0x33, 0x30, 0x33,
0x30, 0x33, 0x30, 0x33, 0x30, 0x33, 0x18, 0x33, 0x98, 0x19, 0x9c, 0x19,
0xcc, 0x19, 0xc0, 0x1c, 0xe0, 0x0c, 0x60, 0x0e, 0x00, 0x06, 0x00, 0x03};
static const ui_bitmap_t bitmap_waves_tx = { static const ui_bitmap_t bitmap_waves_tx = {{16, 24}, bitmap_waves_tx_data};
{ 16, 24 }, bitmap_waves_tx_data
};
__attribute__((unused)) static ui_color_t portapack_color_rgb( __attribute__((unused)) static ui_color_t portapack_color_rgb(
const uint_fast8_t r, const uint_fast8_t r,
const uint_fast8_t g, const uint_fast8_t g,
const uint_fast8_t b const uint_fast8_t b)
) { {
const ui_color_t result = { const ui_color_t result = {
.v = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3) .v = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)};
};
return result; return result;
} }
static const ui_color_t color_background = {0x001f}; static const ui_color_t color_background = {0x001f};
static const ui_color_t color_foreground = {0xffff}; static const ui_color_t color_foreground = {0xffff};
static ui_point_t portapack_lcd_draw_int(const ui_point_t point, uint64_t value, size_t field_width) { static ui_point_t portapack_lcd_draw_int(
const ui_point_t point,
uint64_t value,
size_t field_width)
{
const ui_point_t point_done = { const ui_point_t point_done = {
.x = point.x + font_fixed_8x16.glyph_size.width * field_width, .x = point.x + font_fixed_8x16.glyph_size.width * field_width,
.y = point.y .y = point.y};
};
ui_point_t point_next = point_done; ui_point_t point_next = point_done;
for (size_t i = 0; i < field_width; i++) { for (size_t i = 0; i < field_width; i++) {
@ -293,13 +364,18 @@ static ui_point_t portapack_lcd_draw_int(const ui_point_t point, uint64_t value,
const ui_bitmap_t glyph = portapack_font_glyph(&font_fixed_8x16, c); const ui_bitmap_t glyph = portapack_font_glyph(&font_fixed_8x16, c);
point_next.x -= glyph.size.width; point_next.x -= glyph.size.width;
portapack_draw_bitmap(point_next, glyph, color_foreground, color_background); portapack_draw_bitmap(
point_next,
glyph,
color_foreground,
color_background);
} }
return point_done; return point_done;
} }
static ui_point_t portapack_lcd_draw_string(ui_point_t point, const char* s) { static ui_point_t portapack_lcd_draw_string(ui_point_t point, const char* s)
{
while (*s) { while (*s) {
const char c = *(s++); const char c = *(s++);
const ui_bitmap_t glyph = portapack_font_glyph(&font_fixed_8x16, c); const ui_bitmap_t glyph = portapack_font_glyph(&font_fixed_8x16, c);
@ -349,23 +425,33 @@ typedef enum {
RADIO_DRAW_LIST_ITEM_WAVES = 17, RADIO_DRAW_LIST_ITEM_WAVES = 17,
} radio_draw_list_item_t; } radio_draw_list_item_t;
static ui_point_t portapack_ui_label_point(const radio_draw_list_item_t item) { static ui_point_t portapack_ui_label_point(const radio_draw_list_item_t item)
{
const uint8_t VALUES_X = 72; const uint8_t VALUES_X = 72;
ui_point_t point = {VALUES_X, radio_draw_list[item].point.y + 4}; ui_point_t point = {VALUES_X, radio_draw_list[item].point.y + 4};
return point; return point;
} }
static ui_point_t portapack_ui_draw_string(const radio_draw_list_item_t item, const char* s) { static ui_point_t portapack_ui_draw_string(
const radio_draw_list_item_t item,
const char* s)
{
return portapack_lcd_draw_string(portapack_ui_label_point(item), s); return portapack_lcd_draw_string(portapack_ui_label_point(item), s);
} }
static ui_point_t portapack_ui_draw_db(const radio_draw_list_item_t item, const uint32_t db) { static ui_point_t portapack_ui_draw_db(
const radio_draw_list_item_t item,
const uint32_t db)
{
ui_point_t point = portapack_ui_label_point(item); ui_point_t point = portapack_ui_label_point(item);
point = portapack_lcd_draw_int(point, db, 2); point = portapack_lcd_draw_int(point, db, 2);
return portapack_lcd_draw_string(point, " dB"); return portapack_lcd_draw_string(point, " dB");
} }
static ui_point_t portapack_ui_draw_bw_mhz(const radio_draw_list_item_t item, const uint64_t hz) { static ui_point_t portapack_ui_draw_bw_mhz(
const radio_draw_list_item_t item,
const uint64_t hz)
{
const uint32_t lsd = 1000000 / 100; const uint32_t lsd = 1000000 / 100;
const uint32_t round_offset = lsd / 2; const uint32_t round_offset = lsd / 2;
@ -380,11 +466,19 @@ static ui_point_t portapack_ui_draw_bw_mhz(const radio_draw_list_item_t item, co
return portapack_lcd_draw_string(point, " MHz"); return portapack_lcd_draw_string(point, " MHz");
} }
static void portapack_draw_radio_path_item(const radio_draw_list_item_t item) { static void portapack_draw_radio_path_item(const radio_draw_list_item_t item)
portapack_draw_bitmap(radio_draw_list[item].point, *radio_draw_list[item].bitmap, color_foreground, color_background); {
portapack_draw_bitmap(
radio_draw_list[item].point,
*radio_draw_list[item].bitmap,
color_foreground,
color_background);
} }
static void portapack_radio_path_item_update(const radio_draw_list_item_t item, const ui_bitmap_t* const bitmap) { static void portapack_radio_path_item_update(
const radio_draw_list_item_t item,
const ui_bitmap_t* const bitmap)
{
if (bitmap != radio_draw_list[item].bitmap) { if (bitmap != radio_draw_list[item].bitmap) {
radio_draw_list[item].bitmap = bitmap; radio_draw_list[item].bitmap = bitmap;
portapack_draw_radio_path_item(item); portapack_draw_radio_path_item(item);
@ -394,24 +488,28 @@ static void portapack_radio_path_item_update(const radio_draw_list_item_t item,
static rf_path_direction_t portapack_direction = RF_PATH_DIRECTION_OFF; static rf_path_direction_t portapack_direction = RF_PATH_DIRECTION_OFF;
static bool portapack_lna_on = false; static bool portapack_lna_on = false;
static void portapack_radio_path_redraw() { static void portapack_radio_path_redraw()
{
for (size_t i = 0; i < ARRAY_SIZEOF(radio_draw_list); i++) { for (size_t i = 0; i < ARRAY_SIZEOF(radio_draw_list); i++) {
portapack_draw_radio_path_item(i); portapack_draw_radio_path_item(i);
} }
} }
static void portapack_ui_init(void) { static void portapack_ui_init(void)
{
portapack_clear_display(color_background); portapack_clear_display(color_background);
portapack_backlight(true); portapack_backlight(true);
portapack_radio_path_redraw(); portapack_radio_path_redraw();
} }
static void portapack_ui_deinit(void) { static void portapack_ui_deinit(void)
{
portapack_clear_display(color_background); portapack_clear_display(color_background);
portapack_backlight(false); portapack_backlight(false);
} }
static void portapack_ui_set_frequency(uint64_t frequency) { static void portapack_ui_set_frequency(uint64_t frequency)
{
static char last[10] = " "; static char last[10] = " ";
ui_point_t point = {240 - 20, 16}; ui_point_t point = {240 - 20, 16};
@ -427,7 +525,8 @@ static void portapack_ui_set_frequency(uint64_t frequency) {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
const char c = s[i]; const char c = s[i];
const ui_font_t* const font = (i > 5) ? &font_fixed_24x19 : &font_fixed_16x14; const ui_font_t* const font =
(i > 5) ? &font_fixed_24x19 : &font_fixed_16x14;
point.x -= font->glyph_size.width; point.x -= font->glyph_size.width;
if ((i == 3) || (i == 6) || (i == 9)) { if ((i == 3) || (i == 6) || (i == 9)) {
point.x -= 4; point.x -= 4;
@ -441,14 +540,19 @@ static void portapack_ui_set_frequency(uint64_t frequency) {
const ui_rect_t rect = {point, glyph.size}; const ui_rect_t rect = {point, glyph.size};
portapack_fill_rectangle(rect, color_background); portapack_fill_rectangle(rect, color_background);
} else { } else {
portapack_draw_bitmap(point, glyph, color_foreground, color_background); portapack_draw_bitmap(
point,
glyph,
color_foreground,
color_background);
} }
last[i] = c; last[i] = c;
} }
} }
} }
static void portapack_ui_set_sample_rate(uint32_t sample_rate) { static void portapack_ui_set_sample_rate(uint32_t sample_rate)
{
#if 0 #if 0
ui_point_t point = { VALUES_X, 320 - 1 * 16 }; ui_point_t point = { VALUES_X, 320 - 1 * 16 };
portapack_lcd_draw_int(point, sample_rate, 8); portapack_lcd_draw_int(point, sample_rate, 8);
@ -457,54 +561,81 @@ static void portapack_ui_set_sample_rate(uint32_t sample_rate) {
#endif #endif
} }
static void portapack_ui_set_direction(const rf_path_direction_t direction) { static void portapack_ui_set_direction(const rf_path_direction_t direction)
{
switch (direction) { switch (direction) {
case RF_PATH_DIRECTION_TX: case RF_PATH_DIRECTION_TX:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_waves_tx); portapack_radio_path_item_update(
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, portapack_lna_on ? &bitmap_amp_tx : &bitmap_wire_24); RADIO_DRAW_LIST_ITEM_WAVES,
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, &bitmap_amp_tx); &bitmap_waves_tx);
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, &bitmap_wire_24); portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_RF_AMP,
portapack_lna_on ? &bitmap_amp_tx : &bitmap_wire_24);
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_BB_LNA_AMP,
&bitmap_amp_tx);
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_BB_VGA_AMP,
&bitmap_wire_24);
portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, " "); portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, " ");
break; break;
case RF_PATH_DIRECTION_RX: case RF_PATH_DIRECTION_RX:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_waves_rx); portapack_radio_path_item_update(
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, portapack_lna_on ? &bitmap_amp_rx : &bitmap_wire_24); RADIO_DRAW_LIST_ITEM_WAVES,
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, &bitmap_amp_rx); &bitmap_waves_rx);
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, &bitmap_amp_rx); portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_RF_AMP,
portapack_lna_on ? &bitmap_amp_rx : &bitmap_wire_24);
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_BB_LNA_AMP,
&bitmap_amp_rx);
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_BB_VGA_AMP,
&bitmap_amp_rx);
break; break;
case RF_PATH_DIRECTION_OFF: case RF_PATH_DIRECTION_OFF:
default: default:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_blank_24); portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_WAVES,
&bitmap_blank_24);
break; break;
} }
portapack_direction = direction; portapack_direction = direction;
} }
static void portapack_ui_set_filter_bw(uint32_t bandwidth) { static void portapack_ui_set_filter_bw(uint32_t bandwidth)
{
portapack_ui_draw_bw_mhz(RADIO_DRAW_LIST_ITEM_BB_FILTER, bandwidth); portapack_ui_draw_bw_mhz(RADIO_DRAW_LIST_ITEM_BB_FILTER, bandwidth);
} }
static void portapack_ui_set_lna_power(bool lna_on) { static void portapack_ui_set_lna_power(bool lna_on)
{
portapack_lna_on = lna_on; portapack_lna_on = lna_on;
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, lna_on portapack_radio_path_item_update(
? ((portapack_direction == RF_PATH_DIRECTION_TX) ? &bitmap_amp_tx : &bitmap_amp_rx) RADIO_DRAW_LIST_ITEM_RF_AMP,
: &bitmap_wire_24); lna_on ?
((portapack_direction == RF_PATH_DIRECTION_TX) ? &bitmap_amp_tx :
&bitmap_amp_rx) :
&bitmap_wire_24);
const char* const label = lna_on ? "14 dB" : " "; const char* const label = lna_on ? "14 dB" : " ";
portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_RF_AMP, label); portapack_ui_draw_string(RADIO_DRAW_LIST_ITEM_RF_AMP, label);
} }
static void portapack_ui_set_bb_lna_gain(const uint32_t gain_db) { static void portapack_ui_set_bb_lna_gain(const uint32_t gain_db)
{
portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db); portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db);
} }
static void portapack_ui_set_bb_vga_gain(const uint32_t gain_db) { static void portapack_ui_set_bb_vga_gain(const uint32_t gain_db)
{
portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, gain_db); portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_VGA_AMP, gain_db);
} }
static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) { static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db)
{
/* TODO: This function (and code throughout the HackRF project) is mis-labeled? /* TODO: This function (and code throughout the HackRF project) is mis-labeled?
* According to the MAX2837 datasheet diagram, there is no baseband gain in the TX path. * According to the MAX2837 datasheet diagram, there is no baseband gain in the TX path.
* This gets called when the TX IF gain is changed. * This gets called when the TX IF gain is changed.
@ -512,53 +643,76 @@ static void portapack_ui_set_bb_tx_vga_gain(const uint32_t gain_db) {
portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db); portapack_ui_draw_db(RADIO_DRAW_LIST_ITEM_BB_LNA_AMP, gain_db);
} }
static void portapack_ui_set_first_if_frequency(const uint64_t frequency) { static void portapack_ui_set_first_if_frequency(const uint64_t frequency)
{
(void) frequency; (void) frequency;
} }
static void portapack_ui_set_filter(const rf_path_filter_t filter) { static void portapack_ui_set_filter(const rf_path_filter_t filter)
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_MIXER, (filter == RF_PATH_FILTER_BYPASS) ? &bitmap_wire_24 : &bitmap_mixer); {
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_RF_MIXER,
(filter == RF_PATH_FILTER_BYPASS) ? &bitmap_wire_24 : &bitmap_mixer);
switch (filter) { switch (filter) {
default: default:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_IMAGE_FILTER, &bitmap_wire_24); portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_IMAGE_FILTER,
&bitmap_wire_24);
break; break;
case RF_PATH_FILTER_LOW_PASS: case RF_PATH_FILTER_LOW_PASS:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_IMAGE_FILTER, &bitmap_filter_lp); portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_IMAGE_FILTER,
&bitmap_filter_lp);
break; break;
case RF_PATH_FILTER_HIGH_PASS: case RF_PATH_FILTER_HIGH_PASS:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_IMAGE_FILTER, &bitmap_filter_hp); portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_IMAGE_FILTER,
&bitmap_filter_hp);
break; break;
} }
} }
static void portapack_ui_set_antenna_bias(bool antenna_bias) { static void portapack_ui_set_antenna_bias(bool antenna_bias)
{
(void) antenna_bias; (void) antenna_bias;
} }
static void portapack_ui_set_clock_source(clock_source_t source) { static void portapack_ui_set_clock_source(clock_source_t source)
{
ui_point_t label_point = radio_draw_list[RADIO_DRAW_LIST_ITEM_CLOCK].point; ui_point_t label_point = radio_draw_list[RADIO_DRAW_LIST_ITEM_CLOCK].point;
label_point.x -= 0; label_point.x -= 0;
label_point.y -= 16; label_point.y -= 16;
const char* s = "HRF"; const char* s = "HRF";
switch (source) { switch (source) {
case CLOCK_SOURCE_EXTERNAL: { s = "EXT"; break; } case CLOCK_SOURCE_EXTERNAL: {
case CLOCK_SOURCE_PORTAPACK: { s = "PPK"; break; } s = "EXT";
break;
}
case CLOCK_SOURCE_PORTAPACK: {
s = "PPK";
break;
}
default: default:
case CLOCK_SOURCE_HACKRF: { s = "HRF"; break; } case CLOCK_SOURCE_HACKRF: {
s = "HRF";
break;
}
} }
portapack_lcd_draw_string(label_point, s); portapack_lcd_draw_string(label_point, s);
} }
static void portapack_ui_set_transceiver_mode(transceiver_mode_t mode) { static void portapack_ui_set_transceiver_mode(transceiver_mode_t mode)
{
(void) mode; (void) mode;
} }
static bool portapack_ui_operacake_gpio_compatible(void) { static bool portapack_ui_operacake_gpio_compatible(void)
{
return false; return false;
} }
@ -581,7 +735,8 @@ const hackrf_ui_t portapack_hackrf_ui = {
&portapack_ui_operacake_gpio_compatible, &portapack_ui_operacake_gpio_compatible,
}; };
const hackrf_ui_t* portapack_hackrf_ui_init() { const hackrf_ui_t* portapack_hackrf_ui_init()
{
if (portapack()) { if (portapack()) {
return &portapack_hackrf_ui; return &portapack_hackrf_ui;
} else { } else {

View File

@ -277,8 +277,7 @@ static void rad1o_ui_set_first_if_frequency(const uint64_t frequency
// Not implemented // Not implemented
} }
static void rad1o_ui_set_filter(const rf_path_filter_t filter static void rad1o_ui_set_filter(const rf_path_filter_t filter __attribute__((unused)))
__attribute__((unused)))
{ {
// Not implemented // Not implemented
} }
@ -288,8 +287,7 @@ static void rad1o_ui_set_antenna_bias(bool antenna_bias __attribute__((unused)))
// Not implemented // Not implemented
} }
static void rad1o_ui_set_clock_source(clock_source_t source static void rad1o_ui_set_clock_source(clock_source_t source __attribute__((unused)))
__attribute__((unused)))
{ {
// Not implemented // Not implemented
} }

View File

@ -36,47 +36,51 @@ usb_device_t* usb_device_usb0 = 0;
usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048); usb_queue_head_t usb_qh[12] ATTR_ALIGNED(2048);
#define USB_QH_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) #define USB_QH_INDEX(endpoint_address) \
(((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
usb_queue_head_t* usb_queue_head( usb_queue_head_t* usb_queue_head(const uint_fast8_t endpoint_address)
const uint_fast8_t endpoint_address {
) {
return &usb_qh[USB_QH_INDEX(endpoint_address)]; return &usb_qh[USB_QH_INDEX(endpoint_address)];
} }
usb_endpoint_t* usb_endpoint_from_address( usb_endpoint_t* usb_endpoint_from_address(const uint_fast8_t endpoint_address)
const uint_fast8_t endpoint_address {
) {
return (usb_endpoint_t*) usb_queue_head(endpoint_address)->_reserved_0; return (usb_endpoint_t*) usb_queue_head(endpoint_address)->_reserved_0;
} }
static uint_fast8_t usb_endpoint_address( static uint_fast8_t usb_endpoint_address(
const usb_transfer_direction_t direction, const usb_transfer_direction_t direction,
const uint_fast8_t number const uint_fast8_t number)
) { {
return ((direction == USB_TRANSFER_DIRECTION_IN) ? 0x80 : 0x00) + number; return ((direction == USB_TRANSFER_DIRECTION_IN) ? 0x80 : 0x00) + number;
} }
static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address) { static bool usb_endpoint_is_in(const uint_fast8_t endpoint_address)
{
return (endpoint_address & 0x80) ? true : false; return (endpoint_address & 0x80) ? true : false;
} }
static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address) { static uint_fast8_t usb_endpoint_number(const uint_fast8_t endpoint_address)
{
return (endpoint_address & 0xF); return (endpoint_address & 0xF);
} }
void usb_peripheral_reset() { void usb_peripheral_reset()
{
RESET_CTRL0 = RESET_CTRL0_USB0_RST; RESET_CTRL0 = RESET_CTRL0_USB0_RST;
RESET_CTRL0 = 0; RESET_CTRL0 = 0;
while( (RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0 ); while ((RESET_ACTIVE_STATUS0 & RESET_CTRL0_USB0_RST) == 0) {}
} }
void usb_phy_enable() { void usb_phy_enable()
{
CREG_CREG0 &= ~CREG_CREG0_USB0PHY; CREG_CREG0 &= ~CREG_CREG0_USB0PHY;
} }
static void usb_clear_pending_interrupts(const uint32_t mask) { static void usb_clear_pending_interrupts(const uint32_t mask)
{
USB0_ENDPTNAK = mask; USB0_ENDPTNAK = mask;
USB0_ENDPTNAKEN = mask; USB0_ENDPTNAKEN = mask;
USB0_USBSTS_D = mask; USB0_USBSTS_D = mask;
@ -84,80 +88,85 @@ static void usb_clear_pending_interrupts(const uint32_t mask) {
USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask; USB0_ENDPTCOMPLETE = USB0_ENDPTCOMPLETE & mask;
} }
static void usb_clear_all_pending_interrupts() { static void usb_clear_all_pending_interrupts()
{
usb_clear_pending_interrupts(0xFFFFFFFF); usb_clear_pending_interrupts(0xFFFFFFFF);
} }
static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask) { static void usb_wait_for_endpoint_priming_to_finish(const uint32_t mask)
{
// Wait until controller has parsed new transfer descriptors and prepared // Wait until controller has parsed new transfer descriptors and prepared
// receive buffers. // receive buffers.
while( USB0_ENDPTPRIME & mask ); while (USB0_ENDPTPRIME & mask) {}
} }
static void usb_flush_endpoints(const uint32_t mask) { static void usb_flush_endpoints(const uint32_t mask)
{
// Clear any primed buffers. If a packet is in progress, that transfer // Clear any primed buffers. If a packet is in progress, that transfer
// will continue until completion. // will continue until completion.
USB0_ENDPTFLUSH = mask; USB0_ENDPTFLUSH = mask;
} }
static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask) { static void usb_wait_for_endpoint_flushing_to_finish(const uint32_t mask)
{
// Wait until controller has flushed all endpoints / cleared any primed // Wait until controller has flushed all endpoints / cleared any primed
// buffers. // buffers.
while( USB0_ENDPTFLUSH & mask ); while (USB0_ENDPTFLUSH & mask) {}
} }
static void usb_flush_primed_endpoints(const uint32_t mask) { static void usb_flush_primed_endpoints(const uint32_t mask)
{
usb_wait_for_endpoint_priming_to_finish(mask); usb_wait_for_endpoint_priming_to_finish(mask);
usb_flush_endpoints(mask); usb_flush_endpoints(mask);
usb_wait_for_endpoint_flushing_to_finish(mask); usb_wait_for_endpoint_flushing_to_finish(mask);
} }
static void usb_flush_all_primed_endpoints() { static void usb_flush_all_primed_endpoints()
{
usb_flush_primed_endpoints(0xFFFFFFFF); usb_flush_primed_endpoints(0xFFFFFFFF);
} }
static void usb_endpoint_set_type( static void usb_endpoint_set_type(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
const usb_transfer_type_t transfer_type const usb_transfer_type_t transfer_type)
) { {
// NOTE: UM10503 section 23.6.24 "Endpoint 1 to 5 control registers" says // NOTE: UM10503 section 23.6.24 "Endpoint 1 to 5 control registers" says
// that the disabled side of an endpoint must be set to a non-control type // that the disabled side of an endpoint must be set to a non-control type
// (e.g. bulk, interrupt, or iso). // (e.g. bulk, interrupt, or iso).
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
USB0_ENDPTCTRL(endpoint_number) USB0_ENDPTCTRL(endpoint_number) =
= ( USB0_ENDPTCTRL(endpoint_number) (USB0_ENDPTCTRL(endpoint_number) &
& ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK) ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)) |
) (USB0_ENDPTCTRL_TXT1_0(transfer_type) |
| ( USB0_ENDPTCTRL_TXT1_0(transfer_type) USB0_ENDPTCTRL_RXT(transfer_type));
| USB0_ENDPTCTRL_RXT(transfer_type)
);
} }
static void usb_endpoint_enable( static void usb_endpoint_enable(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR); USB0_ENDPTCTRL(endpoint_number) |=
(USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR);
} else { } else {
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXE | USB0_ENDPTCTRL_RXR); USB0_ENDPTCTRL(endpoint_number) |=
(USB0_ENDPTCTRL_RXE | USB0_ENDPTCTRL_RXR);
} }
} }
static void usb_endpoint_clear_pending_interrupts( static void usb_endpoint_clear_pending_interrupts(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number)); usb_clear_pending_interrupts(
USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number));
} else { } else {
usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number)); usb_clear_pending_interrupts(
USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number));
} }
} }
void usb_endpoint_disable( void usb_endpoint_disable(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_TXE); USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_TXE);
@ -171,16 +180,13 @@ void usb_endpoint_disable(
void usb_endpoint_prime( void usb_endpoint_prime(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const first_td usb_transfer_descriptor_t* const first_td)
) { {
usb_queue_head_t* const qh = usb_queue_head(endpoint->address); usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
qh->next_dtd_pointer = first_td; qh->next_dtd_pointer = first_td;
qh->total_bytes qh->total_bytes &=
&= ~( USB_TD_DTD_TOKEN_STATUS_ACTIVE ~(USB_TD_DTD_TOKEN_STATUS_ACTIVE | USB_TD_DTD_TOKEN_STATUS_HALTED);
| USB_TD_DTD_TOKEN_STATUS_HALTED
)
;
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
@ -190,9 +196,8 @@ void usb_endpoint_prime(
} }
} }
static bool usb_endpoint_is_priming( static bool usb_endpoint_is_priming(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number); return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PETB(1 << endpoint_number);
@ -205,12 +210,12 @@ static bool usb_endpoint_is_priming(
// the given endpoint, waiting until the endpoint has finished. // the given endpoint, waiting until the endpoint has finished.
void usb_endpoint_schedule_wait( void usb_endpoint_schedule_wait(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const td usb_transfer_descriptor_t* const td)
) { {
// Ensure that endpoint is ready to be primed. // Ensure that endpoint is ready to be primed.
// It may have been flushed due to an aborted transaction. // It may have been flushed due to an aborted transaction.
// TODO: This should be preceded by a flush? // TODO: This should be preceded by a flush?
while( usb_endpoint_is_ready(endpoint) ); while (usb_endpoint_is_ready(endpoint)) {}
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
@ -225,8 +230,8 @@ void usb_endpoint_schedule_wait(
void usb_endpoint_schedule_append( void usb_endpoint_schedule_append(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const tail_td, usb_transfer_descriptor_t* const tail_td,
usb_transfer_descriptor_t* const new_td usb_transfer_descriptor_t* const new_td)
) { {
bool done; bool done;
tail_td->next_dtd_pointer = new_td; tail_td->next_dtd_pointer = new_td;
@ -246,9 +251,8 @@ void usb_endpoint_schedule_append(
} }
} }
void usb_endpoint_flush( void usb_endpoint_flush(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
usb_queue_flush_endpoint(endpoint); usb_queue_flush_endpoint(endpoint);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
@ -257,6 +261,7 @@ void usb_endpoint_flush(
usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number)); usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number));
} }
} }
/* /*
static bool usb_endpoint_is_flushing( static bool usb_endpoint_is_flushing(
const usb_endpoint_t* const endpoint const usb_endpoint_t* const endpoint
@ -269,9 +274,8 @@ static bool usb_endpoint_is_flushing(
} }
} }
*/ */
bool usb_endpoint_is_ready( bool usb_endpoint_is_ready(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ETBR(1 << endpoint_number); return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ETBR(1 << endpoint_number);
@ -280,9 +284,8 @@ bool usb_endpoint_is_ready(
} }
} }
bool usb_endpoint_is_complete( bool usb_endpoint_is_complete(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number); return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number);
@ -291,9 +294,8 @@ bool usb_endpoint_is_complete(
} }
} }
void usb_endpoint_stall( void usb_endpoint_stall(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
// Endpoint is to be stalled as a pair -- both OUT and IN. // Endpoint is to be stalled as a pair -- both OUT and IN.
// See UM10503 section 23.10.5.2 "Stalling" // See UM10503 section 23.10.5.2 "Stalling"
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
@ -302,9 +304,8 @@ void usb_endpoint_stall(
// TODO: Also need to reset data toggle in both directions? // TODO: Also need to reset data toggle in both directions?
} }
void usb_endpoint_reset_data_toggle( void usb_endpoint_reset_data_toggle(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address); const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if (usb_endpoint_is_in(endpoint->address)) { if (usb_endpoint_is_in(endpoint->address)) {
USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_TXR; USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_TXR;
@ -313,19 +314,23 @@ void usb_endpoint_reset_data_toggle(
} }
} }
static void usb_controller_run() { static void usb_controller_run()
{
USB0_USBCMD_D |= USB0_USBCMD_D_RS; USB0_USBCMD_D |= USB0_USBCMD_D_RS;
} }
static void usb_controller_stop() { static void usb_controller_stop()
{
USB0_USBCMD_D &= ~USB0_USBCMD_D_RS; USB0_USBCMD_D &= ~USB0_USBCMD_D_RS;
} }
static uint_fast8_t usb_controller_is_resetting() { static uint_fast8_t usb_controller_is_resetting()
{
return (USB0_USBCMD_D & USB0_USBCMD_D_RST) != 0; return (USB0_USBCMD_D & USB0_USBCMD_D_RST) != 0;
} }
static void usb_controller_set_device_mode() { static void usb_controller_set_device_mode()
{
// Set USB0 peripheral mode // Set USB0 peripheral mode
USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2); USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2);
@ -334,9 +339,8 @@ static void usb_controller_set_device_mode() {
USB0_OTGSC = USB0_OTGSC_OT; USB0_OTGSC = USB0_OTGSC_OT;
} }
usb_speed_t usb_speed( usb_speed_t usb_speed(const usb_device_t* const device)
const usb_device_t* const device {
) {
if (device == usb_device_usb0) { if (device == usb_device_usb0) {
switch (USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK) { switch (USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK) {
case USB0_PORTSC1_D_PSPD(0): case USB0_PORTSC1_D_PSPD(0):
@ -356,11 +360,13 @@ usb_speed_t usb_speed(
} }
} }
static void usb_clear_status(const uint32_t status) { static void usb_clear_status(const uint32_t status)
{
USB0_USBSTS_D = status; USB0_USBSTS_D = status;
} }
static uint32_t usb_get_status() { static uint32_t usb_get_status()
{
// Mask status flags with enabled flag interrupts. // Mask status flags with enabled flag interrupts.
const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D; const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D;
@ -372,23 +378,28 @@ static uint32_t usb_get_status() {
return status; return status;
} }
static void usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status) { static void usb_clear_endpoint_setup_status(const uint32_t endpoint_setup_status)
{
USB0_ENDPTSETUPSTAT = endpoint_setup_status; USB0_ENDPTSETUPSTAT = endpoint_setup_status;
} }
static uint32_t usb_get_endpoint_setup_status() { static uint32_t usb_get_endpoint_setup_status()
{
return USB0_ENDPTSETUPSTAT; return USB0_ENDPTSETUPSTAT;
} }
static void usb_clear_endpoint_complete(const uint32_t endpoint_complete) { static void usb_clear_endpoint_complete(const uint32_t endpoint_complete)
{
USB0_ENDPTCOMPLETE = endpoint_complete; USB0_ENDPTCOMPLETE = endpoint_complete;
} }
static uint32_t usb_get_endpoint_complete() { static uint32_t usb_get_endpoint_complete()
{
return USB0_ENDPTCOMPLETE; return USB0_ENDPTCOMPLETE;
} }
static void usb_disable_all_endpoints() { static void usb_disable_all_endpoints()
{
// Endpoint 0 is always enabled. TODO: So why set ENDPTCTRL0? // Endpoint 0 is always enabled. TODO: So why set ENDPTCTRL0?
USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE); USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE);
USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE); USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE);
@ -400,32 +411,30 @@ static void usb_disable_all_endpoints() {
void usb_set_address_immediate( void usb_set_address_immediate(
const usb_device_t* const device, const usb_device_t* const device,
const uint_fast8_t address const uint_fast8_t address)
) { {
if (device == usb_device_usb0) { if (device == usb_device_usb0) {
USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address); USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address);
} }
} }
void usb_set_address_deferred( void usb_set_address_deferred(const usb_device_t* const device, const uint_fast8_t address)
const usb_device_t* const device, {
const uint_fast8_t address
) {
if (device == usb_device_usb0) { if (device == usb_device_usb0) {
USB0_DEVICEADDR USB0_DEVICEADDR =
= USB0_DEVICEADDR_USBADR(address) USB0_DEVICEADDR_USBADR(address) | USB0_DEVICEADDR_USBADRA;
| USB0_DEVICEADDR_USBADRA
;
} }
} }
static void usb_reset_all_endpoints() { static void usb_reset_all_endpoints()
{
usb_disable_all_endpoints(); usb_disable_all_endpoints();
usb_clear_all_pending_interrupts(); usb_clear_all_pending_interrupts();
usb_flush_all_primed_endpoints(); usb_flush_all_primed_endpoints();
} }
static void usb_controller_reset() { static void usb_controller_reset()
{
// TODO: Good to disable some USB interrupts to avoid priming new // TODO: Good to disable some USB interrupts to avoid priming new
// new endpoints before the controller is reset? // new endpoints before the controller is reset?
usb_reset_all_endpoints(); usb_reset_all_endpoints();
@ -437,10 +446,11 @@ static void usb_controller_reset() {
// all primed endpoints and stopping controller. // all primed endpoints and stopping controller.
USB0_USBCMD_D = USB0_USBCMD_D_RST; USB0_USBCMD_D = USB0_USBCMD_D_RST;
while( usb_controller_is_resetting() ); while (usb_controller_is_resetting()) {}
} }
static void usb_bus_reset(usb_device_t* const device) { static void usb_bus_reset(usb_device_t* const device)
{
// According to UM10503 v1.4 section 23.10.3 "Bus reset": // According to UM10503 v1.4 section 23.10.3 "Bus reset":
usb_reset_all_endpoints(); usb_reset_all_endpoints();
usb_set_address_immediate(device, 0); usb_set_address_immediate(device, 0);
@ -458,18 +468,15 @@ static void usb_bus_reset(usb_device_t* const device) {
//} //}
} }
static void usb_interrupt_enable( static void usb_interrupt_enable(usb_device_t* const device)
usb_device_t* const device {
) {
if (device == usb_device_usb0) { if (device == usb_device_usb0) {
nvic_enable_irq(NVIC_USB0_IRQ); nvic_enable_irq(NVIC_USB0_IRQ);
} }
} }
void usb_device_init( void usb_device_init(const uint_fast8_t device_ordinal, usb_device_t* const device)
const uint_fast8_t device_ordinal, {
usb_device_t* const device
) {
if (device_ordinal == 0) { if (device_ordinal == 0) {
usb_device_usb0 = device; usb_device_usb0 = device;
@ -484,11 +491,9 @@ void usb_device_init(
USB0_ENDPOINTLISTADDR = (uint32_t) usb_qh; USB0_ENDPOINTLISTADDR = (uint32_t) usb_qh;
// Enable interrupts // Enable interrupts
USB0_USBINTR_D = USB0_USBINTR_D = USB0_USBINTR_D_UE | USB0_USBINTR_D_UEE |
USB0_USBINTR_D_UE USB0_USBINTR_D_PCE |
| USB0_USBINTR_D_UEE USB0_USBINTR_D_URE
| USB0_USBINTR_D_PCE
| USB0_USBINTR_D_URE
//| USB0_USBINTR_D_SRE //| USB0_USBINTR_D_SRE
| USB0_USBINTR_D_SLE | USB0_USBINTR_D_SLE
//| USB0_USBINTR_D_NAKE //| USB0_USBINTR_D_NAKE
@ -496,14 +501,14 @@ void usb_device_init(
} }
} }
void usb_run( void usb_run(usb_device_t* const device)
usb_device_t* const device {
) {
usb_interrupt_enable(device); usb_interrupt_enable(device);
usb_controller_run(device); usb_controller_run(device);
} }
static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src) { static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src)
{
dst->request_type = src[0]; dst->request_type = src[0];
dst->request = src[1]; dst->request = src[1];
dst->value_l = src[2]; dst->value_l = src[2];
@ -514,34 +519,30 @@ static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src
dst->length_h = src[7]; dst->length_h = src[7];
} }
void usb_endpoint_init( void usb_endpoint_init(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
usb_endpoint_flush(endpoint); usb_endpoint_flush(endpoint);
uint_fast16_t max_packet_size = endpoint->device->descriptor[7]; uint_fast16_t max_packet_size = endpoint->device->descriptor[7];
usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL; usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL;
const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint); const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint);
if (endpoint_descriptor) { if (endpoint_descriptor) {
max_packet_size = usb_endpoint_descriptor_max_packet_size(endpoint_descriptor); max_packet_size =
transfer_type = usb_endpoint_descriptor_transfer_type(endpoint_descriptor); usb_endpoint_descriptor_max_packet_size(endpoint_descriptor);
transfer_type =
usb_endpoint_descriptor_transfer_type(endpoint_descriptor);
} }
// TODO: There are more capabilities to adjust based on the endpoint // TODO: There are more capabilities to adjust based on the endpoint
// descriptor. // descriptor.
usb_queue_head_t* const qh = usb_queue_head(endpoint->address); usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
qh->capabilities qh->capabilities = USB_QH_CAPABILITIES_MULT(0) | USB_QH_CAPABILITIES_ZLT |
= USB_QH_CAPABILITIES_MULT(0) USB_QH_CAPABILITIES_MPL(max_packet_size) |
| USB_QH_CAPABILITIES_ZLT ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS :
| USB_QH_CAPABILITIES_MPL(max_packet_size) 0);
| ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS : 0)
;
qh->current_dtd_pointer = 0; qh->current_dtd_pointer = 0;
qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
qh->total_bytes qh->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(0) | USB_TD_DTD_TOKEN_MULTO(0);
= USB_TD_DTD_TOKEN_TOTAL_BYTES(0)
| USB_TD_DTD_TOKEN_MULTO(0)
;
qh->buffer_pointer_page[0] = 0; qh->buffer_pointer_page[0] = 0;
qh->buffer_pointer_page[1] = 0; qh->buffer_pointer_page[1] = 0;
qh->buffer_pointer_page[2] = 0; qh->buffer_pointer_page[2] = 0;
@ -560,55 +561,65 @@ void usb_endpoint_init(
usb_endpoint_enable(endpoint); usb_endpoint_enable(endpoint);
} }
static void usb_check_for_setup_events() { static void usb_check_for_setup_events()
{
const uint32_t endptsetupstat = usb_get_endpoint_setup_status(); const uint32_t endptsetupstat = usb_get_endpoint_setup_status();
if (endptsetupstat) { if (endptsetupstat) {
for (uint_fast8_t i = 0; i < 6; i++) { for (uint_fast8_t i = 0; i < 6; i++) {
const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i); const uint32_t endptsetupstat_bit =
USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i);
if (endptsetupstat & endptsetupstat_bit) { if (endptsetupstat & endptsetupstat_bit) {
usb_endpoint_t* const endpoint = usb_endpoint_t* const endpoint =
usb_endpoint_from_address( usb_endpoint_from_address(usb_endpoint_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i) USB_TRANSFER_DIRECTION_OUT,
); i));
if (endpoint && endpoint->setup_complete) { if (endpoint && endpoint->setup_complete) {
copy_setup(&endpoint->setup, usb_queue_head(endpoint->address)->setup); copy_setup(
&endpoint->setup,
usb_queue_head(endpoint->address)->setup);
// TODO: Clean up this duplicated effort by providing // TODO: Clean up this duplicated effort by providing
// a cleaner way to get the SETUP data. // a cleaner way to get the SETUP data.
copy_setup(&endpoint->in->setup, usb_queue_head(endpoint->address)->setup); copy_setup(
usb_clear_endpoint_setup_status(endptsetupstat_bit); &endpoint->in->setup,
usb_queue_head(endpoint->address)->setup);
usb_clear_endpoint_setup_status(
endptsetupstat_bit);
endpoint->setup_complete(endpoint); endpoint->setup_complete(endpoint);
} else { } else {
usb_clear_endpoint_setup_status(endptsetupstat_bit); usb_clear_endpoint_setup_status(
endptsetupstat_bit);
} }
} }
} }
} }
} }
static void usb_check_for_transfer_events() { static void usb_check_for_transfer_events()
{
const uint32_t endptcomplete = usb_get_endpoint_complete(); const uint32_t endptcomplete = usb_get_endpoint_complete();
if (endptcomplete) { if (endptcomplete) {
for (uint_fast8_t i = 0; i < 6; i++) { for (uint_fast8_t i = 0; i < 6; i++) {
const uint32_t endptcomplete_out_bit =
const uint32_t endptcomplete_out_bit = USB0_ENDPTCOMPLETE_ERCE(1 << i); USB0_ENDPTCOMPLETE_ERCE(1 << i);
if (endptcomplete & endptcomplete_out_bit) { if (endptcomplete & endptcomplete_out_bit) {
usb_clear_endpoint_complete(endptcomplete_out_bit); usb_clear_endpoint_complete(endptcomplete_out_bit);
usb_endpoint_t* const endpoint = usb_endpoint_t* const endpoint =
usb_endpoint_from_address( usb_endpoint_from_address(usb_endpoint_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i) USB_TRANSFER_DIRECTION_OUT,
); i));
if (endpoint && endpoint->transfer_complete) { if (endpoint && endpoint->transfer_complete) {
endpoint->transfer_complete(endpoint); endpoint->transfer_complete(endpoint);
} }
} }
const uint32_t endptcomplete_in_bit = USB0_ENDPTCOMPLETE_ETCE(1 << i); const uint32_t endptcomplete_in_bit =
USB0_ENDPTCOMPLETE_ETCE(1 << i);
if (endptcomplete & endptcomplete_in_bit) { if (endptcomplete & endptcomplete_in_bit) {
usb_clear_endpoint_complete(endptcomplete_in_bit); usb_clear_endpoint_complete(endptcomplete_in_bit);
usb_endpoint_t* const endpoint = usb_endpoint_t* const endpoint =
usb_endpoint_from_address( usb_endpoint_from_address(usb_endpoint_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_IN, i) USB_TRANSFER_DIRECTION_IN,
); i));
if (endpoint && endpoint->transfer_complete) { if (endpoint && endpoint->transfer_complete) {
endpoint->transfer_complete(endpoint); endpoint->transfer_complete(endpoint);
} }
@ -617,7 +628,8 @@ static void usb_check_for_transfer_events() {
} }
} }
void usb0_isr() { void usb0_isr()
{
const uint32_t status = usb_get_status(); const uint32_t status = usb_get_status();
if (status == 0) { if (status == 0) {

View File

@ -31,75 +31,47 @@
void usb_peripheral_reset(); void usb_peripheral_reset();
void usb_phy_enable(); void usb_phy_enable();
void usb_device_init( void usb_device_init(const uint_fast8_t device_ordinal, usb_device_t* const device);
const uint_fast8_t device_ordinal,
usb_device_t* const device
);
void usb_run( void usb_run(usb_device_t* const device);
usb_device_t* const device
);
void usb_run_tasks( void usb_run_tasks(const usb_device_t* const device);
const usb_device_t* const device
);
usb_speed_t usb_speed( usb_speed_t usb_speed(const usb_device_t* const device);
const usb_device_t* const device
);
void usb_set_address_immediate( void usb_set_address_immediate(
const usb_device_t* const device, const usb_device_t* const device,
const uint_fast8_t address const uint_fast8_t address);
);
void usb_set_address_deferred( void usb_set_address_deferred(
const usb_device_t* const device, const usb_device_t* const device,
const uint_fast8_t address const uint_fast8_t address);
);
usb_endpoint_t* usb_endpoint_from_address( usb_endpoint_t* usb_endpoint_from_address(const uint_fast8_t endpoint_address);
const uint_fast8_t endpoint_address
);
void usb_endpoint_init( void usb_endpoint_init(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
void usb_endpoint_stall( void usb_endpoint_stall(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
void usb_endpoint_disable( void usb_endpoint_disable(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
void usb_endpoint_reset_data_toggle( void usb_endpoint_reset_data_toggle(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
void usb_endpoint_flush( void usb_endpoint_flush(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
bool usb_endpoint_is_ready( bool usb_endpoint_is_ready(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
void usb_endpoint_prime( void usb_endpoint_prime(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const first_td usb_transfer_descriptor_t* const first_td);
);
void usb_endpoint_schedule_wait( void usb_endpoint_schedule_wait(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const td usb_transfer_descriptor_t* const td);
);
void usb_endpoint_schedule_append( void usb_endpoint_schedule_append(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const tail_td, usb_transfer_descriptor_t* const tail_td,
usb_transfer_descriptor_t* const new_td usb_transfer_descriptor_t* const new_td);
);
#endif //__USB_H__ #endif //__USB_H__

View File

@ -33,21 +33,24 @@
usb_queue_t* endpoint_queues[12] = {}; usb_queue_t* endpoint_queues[12] = {};
#define USB_ENDPOINT_INDEX(endpoint_address) (((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1)) #define USB_ENDPOINT_INDEX(endpoint_address) \
(((endpoint_address & 0xF) * 2) + ((endpoint_address >> 7) & 1))
static usb_queue_t* endpoint_queue( static usb_queue_t* endpoint_queue(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
uint32_t index = USB_ENDPOINT_INDEX(endpoint->address); uint32_t index = USB_ENDPOINT_INDEX(endpoint->address);
if (endpoint_queues[index] == NULL) while (1); if (endpoint_queues[index] == NULL) {
while (1) {}
}
return endpoint_queues[index]; return endpoint_queues[index];
} }
void usb_queue_init( void usb_queue_init(usb_queue_t* const queue)
usb_queue_t* const queue {
) {
uint32_t index = USB_ENDPOINT_INDEX(queue->endpoint->address); uint32_t index = USB_ENDPOINT_INDEX(queue->endpoint->address);
if (endpoint_queues[index] != NULL) while (1); if (endpoint_queues[index] != NULL) {
while (1) {}
}
endpoint_queues[index] = queue; endpoint_queues[index] = queue;
usb_transfer_t* t = queue->free_transfers; usb_transfer_t* t = queue->free_transfers;
@ -60,17 +63,19 @@ void usb_queue_init(
} }
/* Allocate a transfer */ /* Allocate a transfer */
static usb_transfer_t* allocate_transfer( static usb_transfer_t* allocate_transfer(usb_queue_t* const queue)
usb_queue_t* const queue {
) {
bool aborted; bool aborted;
usb_transfer_t* transfer; usb_transfer_t* transfer;
if (queue->free_transfers == NULL) if (queue->free_transfers == NULL) {
return NULL; return NULL;
}
do { do {
transfer = (void*) __ldrex((uint32_t*) &queue->free_transfers); transfer = (void*) __ldrex((uint32_t*) &queue->free_transfers);
aborted = __strex((uint32_t) transfer->next, (uint32_t *) &queue->free_transfers); aborted =
__strex((uint32_t) transfer->next,
(uint32_t*) &queue->free_transfers);
} while (aborted); } while (aborted);
transfer->next = NULL; transfer->next = NULL;
return transfer; return transfer;
@ -83,21 +88,23 @@ static void free_transfer(usb_transfer_t* const transfer)
bool aborted; bool aborted;
do { do {
transfer->next = (void*) __ldrex((uint32_t*) &queue->free_transfers); transfer->next = (void*) __ldrex((uint32_t*) &queue->free_transfers);
aborted = __strex((uint32_t) transfer, (uint32_t *) &queue->free_transfers); aborted =
__strex((uint32_t) transfer, (uint32_t*) &queue->free_transfers);
} while (aborted); } while (aborted);
} }
/* Add a transfer to the end of an endpoint's queue. Returns the old /* Add a transfer to the end of an endpoint's queue. Returns the old
* tail or NULL is the queue was empty * tail or NULL is the queue was empty
*/ */
static usb_transfer_t* endpoint_queue_transfer( static usb_transfer_t* endpoint_queue_transfer(usb_transfer_t* const transfer)
usb_transfer_t* const transfer {
) {
usb_queue_t* const queue = transfer->queue; usb_queue_t* const queue = transfer->queue;
transfer->next = NULL; transfer->next = NULL;
if (queue->active != NULL) { if (queue->active != NULL) {
usb_transfer_t* t = queue->active; usb_transfer_t* t = queue->active;
while (t->next != NULL) t = t->next; while (t->next != NULL) {
t = t->next;
}
t->next = transfer; t->next = transfer;
return t; return t;
} else { } else {
@ -127,21 +134,20 @@ int usb_transfer_schedule(
void* const data, void* const data,
const uint32_t maximum_length, const uint32_t maximum_length,
const transfer_completion_cb completion_cb, const transfer_completion_cb completion_cb,
void* const user_data void* const user_data)
) { {
usb_queue_t* const queue = endpoint_queue(endpoint); usb_queue_t* const queue = endpoint_queue(endpoint);
usb_transfer_t* const transfer = allocate_transfer(queue); usb_transfer_t* const transfer = allocate_transfer(queue);
if (transfer == NULL) return -1; if (transfer == NULL) {
return -1;
}
usb_transfer_descriptor_t* const td = &transfer->td; usb_transfer_descriptor_t* const td = &transfer->td;
// Configure the transfer descriptor // Configure the transfer descriptor
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE; td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
td->total_bytes = td->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) |
USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) USB_TD_DTD_TOKEN_IOC | USB_TD_DTD_TOKEN_MULTO(0) |
| USB_TD_DTD_TOKEN_IOC USB_TD_DTD_TOKEN_STATUS_ACTIVE;
| USB_TD_DTD_TOKEN_MULTO(0)
| USB_TD_DTD_TOKEN_STATUS_ACTIVE
;
td->buffer_pointer_page[0] = (uint32_t) data; td->buffer_pointer_page[0] = (uint32_t) data;
td->buffer_pointer_page[1] = ((uint32_t) data + 0x1000) & 0xfffff000; td->buffer_pointer_page[1] = ((uint32_t) data + 0x1000) & 0xfffff000;
td->buffer_pointer_page[2] = ((uint32_t) data + 0x2000) & 0xfffff000; td->buffer_pointer_page[2] = ((uint32_t) data + 0x2000) & 0xfffff000;
@ -171,19 +177,22 @@ int usb_transfer_schedule_block(
void* const data, void* const data,
const uint32_t maximum_length, const uint32_t maximum_length,
const transfer_completion_cb completion_cb, const transfer_completion_cb completion_cb,
void* const user_data void* const user_data)
) { {
int ret; int ret;
do { do {
ret = usb_transfer_schedule(endpoint, data, maximum_length, ret = usb_transfer_schedule(
completion_cb, user_data); endpoint,
data,
maximum_length,
completion_cb,
user_data);
} while (ret == -1); } while (ret == -1);
return 0; return 0;
} }
int usb_transfer_schedule_ack( int usb_transfer_schedule_ack(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
return usb_transfer_schedule_block(endpoint, 0, 0, NULL, NULL); return usb_transfer_schedule_block(endpoint, 0, 0, NULL, NULL);
} }
@ -191,23 +200,26 @@ int usb_transfer_schedule_ack(
void usb_queue_transfer_complete(usb_endpoint_t* const endpoint) void usb_queue_transfer_complete(usb_endpoint_t* const endpoint)
{ {
usb_queue_t* const queue = endpoint_queue(endpoint); usb_queue_t* const queue = endpoint_queue(endpoint);
if (queue == NULL) while(1); // Uh oh if (queue == NULL) {
while (1) {} // Uh oh
}
usb_transfer_t* transfer = queue->active; usb_transfer_t* transfer = queue->active;
while (transfer != NULL) { while (transfer != NULL) {
uint8_t status = transfer->td.total_bytes; uint8_t status = transfer->td.total_bytes;
// Check for failures // Check for failures
if ( status & USB_TD_DTD_TOKEN_STATUS_HALTED if (status & USB_TD_DTD_TOKEN_STATUS_HALTED ||
|| status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR ||
|| status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) { status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) {
// TODO: Uh oh, do something useful here // TODO: Uh oh, do something useful here
while (1); while (1) {}
} }
// Still not finished // Still not finished
if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE) if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE) {
break; break;
}
// Advance the head. We need to do this before invoking the completion // Advance the head. We need to do this before invoking the completion
// callback as it might attempt to schedule a new transfer // callback as it might attempt to schedule a new transfer
@ -215,10 +227,13 @@ void usb_queue_transfer_complete(usb_endpoint_t* const endpoint)
usb_transfer_t* next = transfer->next; usb_transfer_t* next = transfer->next;
// Invoke completion callback // Invoke completion callback
unsigned int total_bytes = (transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >> USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT; unsigned int total_bytes =
(transfer->td.total_bytes & USB_TD_DTD_TOKEN_TOTAL_BYTES_MASK) >>
USB_TD_DTD_TOKEN_TOTAL_BYTES_SHIFT;
unsigned int transferred = transfer->maximum_length - total_bytes; unsigned int transferred = transfer->maximum_length - total_bytes;
if (transfer->completion_cb) if (transfer->completion_cb) {
transfer->completion_cb(transfer->user_data, transferred); transfer->completion_cb(transfer->user_data, transferred);
}
// Advance head and free transfer // Advance head and free transfer
free_transfer(transfer); free_transfer(transfer);

View File

@ -49,15 +49,13 @@ struct _usb_queue_t {
usb_transfer_t* volatile active; usb_transfer_t* volatile active;
}; };
#define USB_DECLARE_QUEUE(endpoint_name) \ #define USB_DECLARE_QUEUE(endpoint_name) struct _usb_queue_t endpoint_name##_queue;
struct _usb_queue_t endpoint_name##_queue;
#define USB_DEFINE_QUEUE(endpoint_name, _pool_size) \ #define USB_DEFINE_QUEUE(endpoint_name, _pool_size) \
struct _usb_transfer_t endpoint_name##_transfers[_pool_size]; \ struct _usb_transfer_t endpoint_name##_transfers[_pool_size]; \
struct _usb_queue_t endpoint_name##_queue = { \ struct _usb_queue_t endpoint_name##_queue = { \
.endpoint = &endpoint_name, \ .endpoint = &endpoint_name, \
.free_transfers = endpoint_name##_transfers, \ .free_transfers = endpoint_name##_transfers, \
.pool_size = _pool_size \ .pool_size = _pool_size};
};
void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint); void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint);
@ -66,27 +64,19 @@ int usb_transfer_schedule(
void* const data, void* const data,
const uint32_t maximum_length, const uint32_t maximum_length,
const transfer_completion_cb completion_cb, const transfer_completion_cb completion_cb,
void* const user_data void* const user_data);
);
int usb_transfer_schedule_block( int usb_transfer_schedule_block(
const usb_endpoint_t* const endpoint, const usb_endpoint_t* const endpoint,
void* const data, void* const data,
const uint32_t maximum_length, const uint32_t maximum_length,
const transfer_completion_cb completion_cb, const transfer_completion_cb completion_cb,
void* const user_data void* const user_data);
);
int usb_transfer_schedule_ack( int usb_transfer_schedule_ack(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
void usb_queue_init( void usb_queue_init(usb_queue_t* const queue);
usb_queue_t* const queue
);
void usb_queue_transfer_complete( void usb_queue_transfer_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
#endif //__USB_QUEUE_H__ #endif //__USB_QUEUE_H__

View File

@ -25,10 +25,8 @@
#include <stdbool.h> #include <stdbool.h>
static void usb_request( static void usb_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
usb_endpoint_t* const endpoint, {
const usb_transfer_stage_t stage
) {
usb_request_status_t status = USB_REQUEST_STATUS_STALL; usb_request_status_t status = USB_REQUEST_STATUS_STALL;
usb_request_handler_fn handler = 0; usb_request_handler_fn handler = 0;
@ -60,17 +58,15 @@ static void usb_request(
} }
} }
void usb_setup_complete( void usb_setup_complete(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) {
usb_request(endpoint, USB_TRANSFER_STAGE_SETUP); usb_request(endpoint, USB_TRANSFER_STAGE_SETUP);
} }
void usb_control_out_complete( void usb_control_out_complete(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) { const bool device_to_host = endpoint->setup.request_type >>
const bool device_to_host = USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if (device_to_host) { if (device_to_host) {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS); usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
} else { } else {
@ -79,11 +75,10 @@ void usb_control_out_complete(
usb_queue_transfer_complete(endpoint); usb_queue_transfer_complete(endpoint);
} }
void usb_control_in_complete( void usb_control_in_complete(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) { const bool device_to_host = endpoint->setup.request_type >>
const bool device_to_host = USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if (device_to_host) { if (device_to_host) {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA); usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
} else { } else {
@ -91,4 +86,3 @@ void usb_control_in_complete(
} }
usb_queue_transfer_complete(endpoint); usb_queue_transfer_complete(endpoint);
} }

View File

@ -44,8 +44,7 @@ typedef enum {
typedef usb_request_status_t (*usb_request_handler_fn)( typedef usb_request_status_t (*usb_request_handler_fn)(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
typedef struct { typedef struct {
usb_request_handler_fn standard; usb_request_handler_fn standard;
@ -56,16 +55,10 @@ typedef struct {
extern const usb_request_handlers_t usb_request_handlers; extern const usb_request_handlers_t usb_request_handlers;
void usb_setup_complete( void usb_setup_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
void usb_control_in_complete( void usb_control_in_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
void usb_control_out_complete( void usb_control_out_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
#endif //__USB_REQUEST_H__ #endif //__USB_REQUEST_H__

View File

@ -28,9 +28,8 @@
#include "usb_type.h" #include "usb_type.h"
#include "usb_queue.h" #include "usb_queue.h"
const uint8_t* usb_endpoint_descriptor( const uint8_t* usb_endpoint_descriptor(const usb_endpoint_t* const endpoint)
const usb_endpoint_t* const endpoint {
) {
const usb_configuration_t* const configuration = endpoint->device->configuration; const usb_configuration_t* const configuration = endpoint->device->configuration;
if (configuration) { if (configuration) {
const uint8_t* descriptor = configuration->descriptor; const uint8_t* descriptor = configuration->descriptor;
@ -48,33 +47,30 @@ const uint8_t* usb_endpoint_descriptor(
} }
uint_fast16_t usb_endpoint_descriptor_max_packet_size( uint_fast16_t usb_endpoint_descriptor_max_packet_size(
const uint8_t* const endpoint_descriptor const uint8_t* const endpoint_descriptor)
) { {
return (endpoint_descriptor[5] << 8) | endpoint_descriptor[4]; return (endpoint_descriptor[5] << 8) | endpoint_descriptor[4];
} }
usb_transfer_type_t usb_endpoint_descriptor_transfer_type( usb_transfer_type_t usb_endpoint_descriptor_transfer_type(
const uint8_t* const endpoint_descriptor const uint8_t* const endpoint_descriptor)
) { {
return (endpoint_descriptor[3] & 0x3); return (endpoint_descriptor[3] & 0x3);
} }
void (*usb_configuration_changed_cb)(usb_device_t* const) = NULL; void (*usb_configuration_changed_cb)(usb_device_t* const) = NULL;
void usb_set_configuration_changed_cb( void usb_set_configuration_changed_cb(void (*callback)(usb_device_t* const))
void (*callback)(usb_device_t* const) {
) {
usb_configuration_changed_cb = callback; usb_configuration_changed_cb = callback;
} }
bool usb_set_configuration( bool usb_set_configuration(
usb_device_t* const device, usb_device_t* const device,
const uint_fast8_t configuration_number const uint_fast8_t configuration_number)
) { {
const usb_configuration_t* new_configuration = 0; const usb_configuration_t* new_configuration = 0;
if (configuration_number != 0) { if (configuration_number != 0) {
// Locate requested configuration. // Locate requested configuration.
if (device->configurations) { if (device->configurations) {
usb_configuration_t** configurations = *(device->configurations); usb_configuration_t** configurations = *(device->configurations);
@ -101,16 +97,17 @@ bool usb_set_configuration(
device->configuration = new_configuration; device->configuration = new_configuration;
} }
if (usb_configuration_changed_cb) if (usb_configuration_changed_cb) {
usb_configuration_changed_cb(device); usb_configuration_changed_cb(device);
}
return true; return true;
} }
static usb_request_status_t usb_send_descriptor( static usb_request_status_t usb_send_descriptor(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const uint8_t* const descriptor_data const uint8_t* const descriptor_data)
) { {
const uint32_t setup_length = endpoint->setup.length; const uint32_t setup_length = endpoint->setup.length;
uint32_t descriptor_length = descriptor_data[0]; uint32_t descriptor_length = descriptor_data[0];
if (descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION) { if (descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
@ -121,23 +118,27 @@ static usb_request_status_t usb_send_descriptor(
endpoint->in, endpoint->in,
(uint8_t* const) descriptor_data, (uint8_t* const) descriptor_data,
(setup_length > descriptor_length) ? descriptor_length : setup_length, (setup_length > descriptor_length) ? descriptor_length : setup_length,
NULL, NULL NULL,
); NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
static usb_request_status_t usb_send_descriptor_string( static usb_request_status_t usb_send_descriptor_string(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) {
if ((endpoint->setup.value_l == 0xee) && if ((endpoint->setup.value_l == 0xee) &&
(endpoint->device->wcid_string_descriptor != NULL)) { /* MS WCID string */ (endpoint->device->wcid_string_descriptor != NULL)) { /* MS WCID string */
return usb_send_descriptor(endpoint, endpoint->device->wcid_string_descriptor); return usb_send_descriptor(
endpoint,
endpoint->device->wcid_string_descriptor);
} else { } else {
uint_fast8_t index = endpoint->setup.value_l; uint_fast8_t index = endpoint->setup.value_l;
for( uint_fast8_t i=0; endpoint->device->descriptor_strings[i] != 0; i++ ) { for (uint_fast8_t i = 0; endpoint->device->descriptor_strings[i] != 0;
i++) {
if (i == index) { if (i == index) {
return usb_send_descriptor(endpoint, endpoint->device->descriptor_strings[i]); return usb_send_descriptor(
endpoint,
endpoint->device->descriptor_strings[i]);
} }
} }
} }
@ -147,14 +148,16 @@ static usb_request_status_t usb_send_descriptor_string(
static usb_request_status_t usb_send_descriptor_config( static usb_request_status_t usb_send_descriptor_config(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
usb_speed_t speed, usb_speed_t speed,
const uint8_t config_num const uint8_t config_num)
) { {
usb_configuration_t** config = *(endpoint->device->configurations); usb_configuration_t** config = *(endpoint->device->configurations);
unsigned int i = 0; unsigned int i = 0;
for (; *config != NULL; config++) { for (; *config != NULL; config++) {
if ((*config)->speed == speed) { if ((*config)->speed == speed) {
if (i == config_num) { if (i == config_num) {
return usb_send_descriptor(endpoint, (*config)->descriptor); return usb_send_descriptor(
endpoint,
(*config)->descriptor);
} else { } else {
i++; i++;
} }
@ -164,8 +167,8 @@ static usb_request_status_t usb_send_descriptor_config(
} }
static usb_request_status_t usb_standard_request_get_descriptor_setup( static usb_request_status_t usb_standard_request_get_descriptor_setup(
usb_endpoint_t* const endpoint usb_endpoint_t* const endpoint)
) { {
switch (endpoint->setup.value_h) { switch (endpoint->setup.value_h) {
case USB_DESCRIPTOR_TYPE_DEVICE: case USB_DESCRIPTOR_TYPE_DEVICE:
return usb_send_descriptor(endpoint, endpoint->device->descriptor); return usb_send_descriptor(endpoint, endpoint->device->descriptor);
@ -173,20 +176,34 @@ static usb_request_status_t usb_standard_request_get_descriptor_setup(
case USB_DESCRIPTOR_TYPE_CONFIGURATION: case USB_DESCRIPTOR_TYPE_CONFIGURATION:
// TODO: Duplicated code. Refactor. // TODO: Duplicated code. Refactor.
if (usb_speed(endpoint->device) == USB_SPEED_HIGH) { if (usb_speed(endpoint->device) == USB_SPEED_HIGH) {
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l); return usb_send_descriptor_config(
endpoint,
USB_SPEED_HIGH,
endpoint->setup.value_l);
} else { } else {
return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l); return usb_send_descriptor_config(
endpoint,
USB_SPEED_FULL,
endpoint->setup.value_l);
} }
case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
return usb_send_descriptor(endpoint, endpoint->device->qualifier_descriptor); return usb_send_descriptor(
endpoint,
endpoint->device->qualifier_descriptor);
case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION: case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
// TODO: Duplicated code. Refactor. // TODO: Duplicated code. Refactor.
if (usb_speed(endpoint->device) == USB_SPEED_HIGH) { if (usb_speed(endpoint->device) == USB_SPEED_HIGH) {
return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l); return usb_send_descriptor_config(
endpoint,
USB_SPEED_FULL,
endpoint->setup.value_l);
} else { } else {
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l); return usb_send_descriptor_config(
endpoint,
USB_SPEED_HIGH,
endpoint->setup.value_l);
} }
case USB_DESCRIPTOR_TYPE_STRING: case USB_DESCRIPTOR_TYPE_STRING:
@ -201,8 +218,8 @@ static usb_request_status_t usb_standard_request_get_descriptor_setup(
static usb_request_status_t usb_standard_request_get_descriptor( static usb_request_status_t usb_standard_request_get_descriptor(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
switch (stage) { switch (stage) {
case USB_TRANSFER_STAGE_SETUP: case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_descriptor_setup(endpoint); return usb_standard_request_get_descriptor_setup(endpoint);
@ -218,17 +235,21 @@ static usb_request_status_t usb_standard_request_get_descriptor(
usb_request_status_t usb_vendor_request_read_wcid( usb_request_status_t usb_vendor_request_read_wcid(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
if ((endpoint->setup.index == 0x04) && if ((endpoint->setup.index == 0x04) &&
(endpoint->device->wcid_feature_descriptor != NULL)) { (endpoint->device->wcid_feature_descriptor != NULL)) {
usb_send_descriptor(endpoint, endpoint->device->wcid_feature_descriptor); usb_send_descriptor(
endpoint,
endpoint->device->wcid_feature_descriptor);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
if ((endpoint->setup.index == 0x05) && if ((endpoint->setup.index == 0x05) &&
(endpoint->device->wcid_extended_properties_descriptor != NULL)) { (endpoint->device->wcid_extended_properties_descriptor != NULL)) {
usb_send_descriptor(endpoint, endpoint->device->wcid_extended_properties_descriptor); usb_send_descriptor(
endpoint,
endpoint->device->wcid_extended_properties_descriptor);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
@ -239,8 +260,8 @@ usb_request_status_t usb_vendor_request_read_wcid(
/*********************************************************************/ /*********************************************************************/
static usb_request_status_t usb_standard_request_set_address_setup( static usb_request_status_t usb_standard_request_set_address_setup(
usb_endpoint_t* const endpoint usb_endpoint_t* const endpoint)
) { {
usb_set_address_deferred(endpoint->device, endpoint->setup.value_l); usb_set_address_deferred(endpoint->device, endpoint->setup.value_l);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
@ -248,8 +269,8 @@ static usb_request_status_t usb_standard_request_set_address_setup(
static usb_request_status_t usb_standard_request_set_address( static usb_request_status_t usb_standard_request_set_address(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
switch (stage) { switch (stage) {
case USB_TRANSFER_STAGE_SETUP: case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_set_address_setup(endpoint); return usb_standard_request_set_address_setup(endpoint);
@ -270,8 +291,8 @@ static usb_request_status_t usb_standard_request_set_address(
/*********************************************************************/ /*********************************************************************/
static usb_request_status_t usb_standard_request_set_configuration_setup( static usb_request_status_t usb_standard_request_set_configuration_setup(
usb_endpoint_t* const endpoint usb_endpoint_t* const endpoint)
) { {
const uint8_t usb_configuration = endpoint->setup.value_l; const uint8_t usb_configuration = endpoint->setup.value_l;
if (usb_set_configuration(endpoint->device, usb_configuration)) { if (usb_set_configuration(endpoint->device, usb_configuration)) {
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
@ -283,8 +304,8 @@ static usb_request_status_t usb_standard_request_set_configuration_setup(
static usb_request_status_t usb_standard_request_set_configuration( static usb_request_status_t usb_standard_request_set_configuration(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
switch (stage) { switch (stage) {
case USB_TRANSFER_STAGE_SETUP: case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_set_configuration_setup(endpoint); return usb_standard_request_set_configuration_setup(endpoint);
@ -301,14 +322,19 @@ static usb_request_status_t usb_standard_request_set_configuration(
/*********************************************************************/ /*********************************************************************/
static usb_request_status_t usb_standard_request_get_configuration_setup( static usb_request_status_t usb_standard_request_get_configuration_setup(
usb_endpoint_t* const endpoint usb_endpoint_t* const endpoint)
) { {
if (endpoint->setup.length == 1) { if (endpoint->setup.length == 1) {
endpoint->buffer[0] = 0; endpoint->buffer[0] = 0;
if (endpoint->device->configuration) { if (endpoint->device->configuration) {
endpoint->buffer[0] = endpoint->device->configuration->number; endpoint->buffer[0] = endpoint->device->configuration->number;
} }
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL); usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else { } else {
@ -318,8 +344,8 @@ static usb_request_status_t usb_standard_request_get_configuration_setup(
static usb_request_status_t usb_standard_request_get_configuration( static usb_request_status_t usb_standard_request_get_configuration(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
switch (stage) { switch (stage) {
case USB_TRANSFER_STAGE_SETUP: case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_configuration_setup(endpoint); return usb_standard_request_get_configuration_setup(endpoint);
@ -334,13 +360,18 @@ static usb_request_status_t usb_standard_request_get_configuration(
} }
static usb_request_status_t usb_standard_request_get_status_setup( static usb_request_status_t usb_standard_request_get_status_setup(
usb_endpoint_t* const endpoint usb_endpoint_t* const endpoint)
) { {
if (endpoint->setup.length == 2) { if (endpoint->setup.length == 2) {
endpoint->buffer[0] = 0; endpoint->buffer[0] = 0;
endpoint->buffer[1] = 0; endpoint->buffer[1] = 0;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, NULL, NULL); usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
2,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else { } else {
@ -348,11 +379,10 @@ static usb_request_status_t usb_standard_request_get_status_setup(
} }
} }
static usb_request_status_t usb_standard_request_get_status( static usb_request_status_t usb_standard_request_get_status(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
switch (stage) { switch (stage) {
case USB_TRANSFER_STAGE_SETUP: case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_status_setup(endpoint); return usb_standard_request_get_status_setup(endpoint);
@ -369,12 +399,10 @@ static usb_request_status_t usb_standard_request_get_status(
static usb_request_status_t usb_standard_request_clear_feature_setup( static usb_request_status_t usb_standard_request_clear_feature_setup(
usb_endpoint_t* const endpoint) usb_endpoint_t* const endpoint)
{ {
switch (endpoint->setup.value) { switch (endpoint->setup.value) {
case USB_FEATURE_SELECTOR_ENDPOINT_HALT: case USB_FEATURE_SELECTOR_ENDPOINT_HALT:
usb_endpoint_reset_data_toggle( usb_endpoint_reset_data_toggle(
usb_endpoint_from_address(endpoint->setup.index) usb_endpoint_from_address(endpoint->setup.index));
);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
default: default:
@ -403,8 +431,8 @@ static usb_request_status_t usb_standard_request_clear_feature(
usb_request_status_t usb_standard_request( usb_request_status_t usb_standard_request(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
switch (endpoint->setup.request) { switch (endpoint->setup.request) {
case USB_STANDARD_REQUEST_GET_STATUS: case USB_STANDARD_REQUEST_GET_STATUS:
return usb_standard_request_get_status(endpoint, stage); return usb_standard_request_get_status(endpoint, stage);

View File

@ -25,35 +25,26 @@
#include "usb_type.h" #include "usb_type.h"
#include "usb_request.h" #include "usb_request.h"
void usb_set_configuration_changed_cb( void usb_set_configuration_changed_cb(void (*callback)(usb_device_t* const));
void (*callback)(usb_device_t* const)
);
usb_request_status_t usb_vendor_request_read_wcid( usb_request_status_t usb_vendor_request_read_wcid(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_standard_request( usb_request_status_t usb_standard_request(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
const uint8_t* usb_endpoint_descriptor( const uint8_t* usb_endpoint_descriptor(const usb_endpoint_t* const endpoint);
const usb_endpoint_t* const endpoint
);
uint_fast16_t usb_endpoint_descriptor_max_packet_size( uint_fast16_t usb_endpoint_descriptor_max_packet_size(
const uint8_t* const endpoint_descriptor const uint8_t* const endpoint_descriptor);
);
usb_transfer_type_t usb_endpoint_descriptor_transfer_type( usb_transfer_type_t usb_endpoint_descriptor_transfer_type(
const uint8_t* const endpoint_descriptor const uint8_t* const endpoint_descriptor);
);
bool usb_set_configuration( bool usb_set_configuration(
usb_device_t* const device, usb_device_t* const device,
const uint_fast8_t configuration_number const uint_fast8_t configuration_number);
);
#endif //__USB_STANDARD_REQUEST_H__ #endif //__USB_STANDARD_REQUEST_H__

View File

@ -33,25 +33,31 @@
typedef struct ATTR_PACKED { typedef struct ATTR_PACKED {
uint8_t request_type; uint8_t request_type;
uint8_t request; uint8_t request;
union { union {
struct { struct {
uint8_t value_l; uint8_t value_l;
uint8_t value_h; uint8_t value_h;
}; };
uint16_t value; uint16_t value;
}; };
union { union {
struct { struct {
uint8_t index_l; uint8_t index_l;
uint8_t index_h; uint8_t index_h;
}; };
uint16_t index; uint16_t index;
}; };
union { union {
struct { struct {
uint8_t length_l; uint8_t length_l;
uint8_t length_h; uint8_t length_h;
}; };
uint16_t length; uint16_t length;
}; };
} usb_setup_t; } usb_setup_t;
@ -84,9 +90,12 @@ typedef enum {
USB_SETUP_REQUEST_TYPE_RESERVED = 3 << USB_SETUP_REQUEST_TYPE_shift, USB_SETUP_REQUEST_TYPE_RESERVED = 3 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift = 7, USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift = 7,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_mask = 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift, USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_mask =
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_HOST_TO_DEVICE = 0 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift, 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_DEVICE_TO_HOST = 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift, USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_HOST_TO_DEVICE =
0 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_DEVICE_TO_HOST =
1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
} usb_setup_request_type_t; } usb_setup_request_type_t;
typedef enum { typedef enum {
@ -137,6 +146,7 @@ typedef struct {
} usb_device_t; } usb_device_t;
typedef struct usb_endpoint_t usb_endpoint_t; typedef struct usb_endpoint_t usb_endpoint_t;
struct usb_endpoint_t { struct usb_endpoint_t {
usb_setup_t setup; usb_setup_t setup;
uint8_t buffer[8]; // Buffer for use during IN stage. uint8_t buffer[8]; // Buffer for use during IN stage.

View File

@ -80,10 +80,7 @@ uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
/* Release power down / Device ID */ /* Release power down / Device ID */
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv) uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
{ {
uint8_t data[] = { uint8_t data[] = {W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF};
W25Q80BV_DEVICE_ID,
0xFF, 0xFF, 0xFF, 0xFF
};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
return data[4]; return data[4];
} }
@ -92,9 +89,18 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t*
{ {
uint8_t data[] = { uint8_t data[] = {
W25Q80BV_UNIQUE_ID, W25Q80BV_UNIQUE_ID,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF,
}; 0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
for (size_t i = 0; i < 8; i++) { for (size_t i = 0; i < 8; i++) {
@ -104,7 +110,7 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t*
void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv) void w25q80bv_wait_while_busy(w25q80bv_driver_t* const drv)
{ {
while (w25q80bv_get_status(drv) & W25Q80BV_STATUS_BUSY); while (w25q80bv_get_status(drv) & W25Q80BV_STATUS_BUSY) {}
} }
void w25q80bv_write_enable(w25q80bv_driver_t* const drv) void w25q80bv_write_enable(w25q80bv_driver_t* const drv)
@ -113,7 +119,7 @@ void w25q80bv_write_enable(w25q80bv_driver_t* const drv)
uint8_t data[] = {W25Q80BV_WRITE_ENABLE}; uint8_t data[] = {W25Q80BV_WRITE_ENABLE};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
while (!(w25q80bv_get_status(drv) & W25Q80BV_STATUS_WEL)); while (!(w25q80bv_get_status(drv) & W25Q80BV_STATUS_WEL)) {}
} }
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv) void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
@ -133,15 +139,21 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
} }
/* write up a 256 byte page or partial page */ /* write up a 256 byte page or partial page */
static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, uint8_t* data) static void w25q80bv_page_program(
w25q80bv_driver_t* const drv,
const uint32_t addr,
const uint16_t len,
uint8_t* data)
{ {
/* do nothing if asked to write beyond a page boundary */ /* do nothing if asked to write beyond a page boundary */
if (((addr & 0xFF) + len) > drv->page_len) if (((addr & 0xFF) + len) > drv->page_len) {
return; return;
}
/* do nothing if we would overflow the flash */ /* do nothing if we would overflow the flash */
if (addr > (drv->num_bytes - len)) if (addr > (drv->num_bytes - len)) {
return; return;
}
w25q80bv_wait_while_busy(drv); w25q80bv_wait_while_busy(drv);
w25q80bv_write_enable(drv); w25q80bv_write_enable(drv);
@ -150,19 +162,19 @@ static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t a
W25Q80BV_PAGE_PROGRAM, W25Q80BV_PAGE_PROGRAM,
(addr & 0xFF0000) >> 16, (addr & 0xFF0000) >> 16,
(addr & 0xFF00) >> 8, (addr & 0xFF00) >> 8,
addr & 0xFF addr & 0xFF};
};
const spi_transfer_t transfers[] = { const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}};
{ header, ARRAY_SIZE(header) },
{ data, len }
};
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
} }
/* write an arbitrary number of bytes */ /* write an arbitrary number of bytes */
void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* data) void w25q80bv_program(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* data)
{ {
uint16_t first_block_len; uint16_t first_block_len;
uint8_t device_id; uint8_t device_id;
@ -173,14 +185,16 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len,
device_id != W25Q16DV_DEVICE_ID_RES); device_id != W25Q16DV_DEVICE_ID_RES);
/* do nothing if we would overflow the flash */ /* do nothing if we would overflow the flash */
if ((len > drv->num_bytes) || (addr > drv->num_bytes) if ((len > drv->num_bytes) || (addr > drv->num_bytes) ||
|| ((addr + len) > drv->num_bytes)) ((addr + len) > drv->num_bytes)) {
return; return;
}
/* handle start not at page boundary */ /* handle start not at page boundary */
first_block_len = drv->page_len - (addr % drv->page_len); first_block_len = drv->page_len - (addr % drv->page_len);
if (len < first_block_len) if (len < first_block_len) {
first_block_len = len; first_block_len = len;
}
if (first_block_len) { if (first_block_len) {
w25q80bv_page_program(drv, addr, first_block_len, data); w25q80bv_page_program(drv, addr, first_block_len, data);
addr += first_block_len; addr += first_block_len;
@ -203,12 +217,17 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len,
} }
/* write an arbitrary number of bytes */ /* write an arbitrary number of bytes */
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data) void w25q80bv_read(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* const data)
{ {
/* do nothing if we would overflow the flash */ /* do nothing if we would overflow the flash */
if ((len > drv->num_bytes) || (addr > drv->num_bytes) if ((len > drv->num_bytes) || (addr > drv->num_bytes) ||
|| ((addr + len) > drv->num_bytes)) ((addr + len) > drv->num_bytes)) {
return; return;
}
w25q80bv_wait_while_busy(drv); w25q80bv_wait_while_busy(drv);
@ -217,13 +236,9 @@ void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, ui
(addr & 0xFF0000) >> 16, (addr & 0xFF0000) >> 16,
(addr & 0xFF00) >> 8, (addr & 0xFF00) >> 8,
addr & 0xFF, addr & 0xFF,
0x00 0x00};
};
const spi_transfer_t transfers[] = { const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}};
{ header, ARRAY_SIZE(header) },
{ data, len }
};
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
} }

View File

@ -32,8 +32,7 @@
#include "spi_bus.h" #include "spi_bus.h"
#include "gpio.h" #include "gpio.h"
typedef union typedef union {
{
uint64_t id_64b; uint64_t id_64b;
uint32_t id_32b[2]; /* 2*32bits 64bits Unique ID */ uint32_t id_32b[2]; /* 2*32bits 64bits Unique ID */
uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */
@ -55,10 +54,18 @@ struct w25q80bv_driver_t {
void w25q80bv_setup(w25q80bv_driver_t* const drv); void w25q80bv_setup(w25q80bv_driver_t* const drv);
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data); void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data);
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv); void w25q80bv_chip_erase(w25q80bv_driver_t* const drv);
void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* data); void w25q80bv_program(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* data);
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv); uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv);
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id); void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id);
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data); void w25q80bv_read(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* const data);
void w25q80bv_clear_status(w25q80bv_driver_t* const drv); void w25q80bv_clear_status(w25q80bv_driver_t* const drv);
#endif //__W25Q80BV_H__ #endif //__W25Q80BV_H__

View File

@ -28,16 +28,24 @@
* automatically? * automatically?
*/ */
void w25q80bv_target_init(w25q80bv_driver_t* const drv) { void w25q80bv_target_init(w25q80bv_driver_t* const drv)
{
(void) drv; (void) drv;
/* Init SPIFI GPIO to Normal GPIO */ /* Init SPIFI GPIO to Normal GPIO */
scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2)); // P3_3 SPIFI_SCK => SSP0_SCK
scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14] // P3_3 SPIFI_SCK => SSP0_SCK
scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15] scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2));
scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_6 SPIFI SPIFI_CIPO IO1 => GPIO0[6] // P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14]
scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_7 SPIFI SPIFI_COPI IO0 => GPIO5[10] scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0));
scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_8 SPIFI SPIFI_CS => GPIO5[11] // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15]
scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0));
// P3_6 SPIFI SPIFI_CIPO IO1 => GPIO0[6]
scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0));
// P3_7 SPIFI SPIFI_COPI IO0 => GPIO5[10]
scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4));
// P3_8 SPIFI SPIFI_CS => GPIO5[11]
scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4));
/* configure SSP pins */ /* configure SSP pins */
scu_pinmux(SCU_SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));

View File

@ -125,12 +125,13 @@ static const uint32_t vendor_request_handler_count =
usb_request_status_t usb_vendor_request( usb_request_status_t usb_vendor_request(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
usb_request_status_t status = USB_REQUEST_STATUS_STALL; usb_request_status_t status = USB_REQUEST_STATUS_STALL;
if (endpoint->setup.request < vendor_request_handler_count) { if (endpoint->setup.request < vendor_request_handler_count) {
usb_request_handler_fn handler = vendor_request_handler[endpoint->setup.request]; usb_request_handler_fn handler =
vendor_request_handler[endpoint->setup.request];
if (handler) { if (handler) {
status = handler(endpoint, stage); status = handler(endpoint, stage);
} }
@ -146,9 +147,8 @@ const usb_request_handlers_t usb_request_handlers = {
.reserved = 0, .reserved = 0,
}; };
void usb_configuration_changed( void usb_configuration_changed(usb_device_t* const device)
usb_device_t* const device {
) {
/* Reset transceiver to idle state until other commands are received */ /* Reset transceiver to idle state until other commands are received */
request_transceiver_mode(TRANSCEIVER_MODE_OFF); request_transceiver_mode(TRANSCEIVER_MODE_OFF);
if (device->configuration->number == 1) { if (device->configuration->number == 1) {
@ -171,13 +171,18 @@ void usb_set_descriptor_by_serial_number(void)
iap_cmd_call(&iap_cmd_res); iap_cmd_call(&iap_cmd_res);
if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) { if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) {
usb_descriptor_string_serial_number[0] = USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN; usb_descriptor_string_serial_number[0] =
USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN;
usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING; usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING;
/* 32 characters of serial number, convert to UTF-16LE */ /* 32 characters of serial number, convert to UTF-16LE */
for (size_t i = 0; i < USB_DESCRIPTOR_STRING_SERIAL_LEN; i++) { for (size_t i = 0; i < USB_DESCRIPTOR_STRING_SERIAL_LEN; i++) {
const uint_fast8_t nibble = (iap_cmd_res.status_res.iap_result[i >> 3] >> (28 - (i & 7) * 4)) & 0xf; const uint_fast8_t nibble =
const char c = (nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble); (iap_cmd_res.status_res.iap_result[i >> 3] >>
(28 - (i & 7) * 4)) &
0xf;
const char c =
(nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble);
usb_descriptor_string_serial_number[2 + i * 2] = c; usb_descriptor_string_serial_number[2 + i * 2] = c;
usb_descriptor_string_serial_number[3 + i * 2] = 0x00; usb_descriptor_string_serial_number[3 + i * 2] = 0x00;
} }
@ -187,15 +192,20 @@ void usb_set_descriptor_by_serial_number(void)
} }
} }
static bool cpld_jtag_sram_load(jtag_t* const jtag) { static bool cpld_jtag_sram_load(jtag_t* const jtag)
{
cpld_jtag_take(jtag); cpld_jtag_take(jtag);
cpld_xc2c64a_jtag_sram_write(jtag, &cpld_hackrf_program_sram); cpld_xc2c64a_jtag_sram_write(jtag, &cpld_hackrf_program_sram);
const bool success = cpld_xc2c64a_jtag_sram_verify(jtag, &cpld_hackrf_program_sram, &cpld_hackrf_verify); const bool success = cpld_xc2c64a_jtag_sram_verify(
jtag,
&cpld_hackrf_program_sram,
&cpld_hackrf_verify);
cpld_jtag_release(jtag); cpld_jtag_release(jtag);
return success; return success;
} }
static void m0_rom_to_ram() { static void m0_rom_to_ram()
{
uint32_t* dest = &__ram_m0_start__; uint32_t* dest = &__ram_m0_start__;
// Calculate the base address of ROM // Calculate the base address of ROM
@ -208,7 +218,8 @@ static void m0_rom_to_ram() {
memcpy(dest, (uint32_t*) (base + src), len); memcpy(dest, (uint32_t*) (base + src), len);
} }
int main(void) { int main(void)
{
// Copy M0 image from ROM before SPIFI is disabled // Copy M0 image from ROM before SPIFI is disabled
m0_rom_to_ram(); m0_rom_to_ram();

View File

@ -33,43 +33,57 @@
char version_string[] = VERSION_STRING; char version_string[] = VERSION_STRING;
usb_request_status_t usb_vendor_request_read_board_id( usb_request_status_t usb_vendor_request_read_board_id(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
endpoint->buffer[0] = BOARD_ID; endpoint->buffer[0] = BOARD_ID;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, NULL, NULL); usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
} }
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
usb_request_status_t usb_vendor_request_read_version_string( usb_request_status_t usb_vendor_request_read_version_string(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint8_t length; uint8_t length;
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
length = (uint8_t) strlen(version_string); length = (uint8_t) strlen(version_string);
usb_transfer_schedule_block(endpoint->in, version_string, length, NULL, NULL); usb_transfer_schedule_block(
endpoint->in,
version_string,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
} }
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
static read_partid_serialno_t read_partid_serialno; static read_partid_serialno_t read_partid_serialno;
usb_request_status_t usb_vendor_request_read_partid_serialno( usb_request_status_t usb_vendor_request_read_partid_serialno(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint8_t length; uint8_t length;
iap_cmd_res_t iap_cmd_res; iap_cmd_res_t iap_cmd_res;
if (stage == USB_TRANSFER_STAGE_SETUP) if (stage == USB_TRANSFER_STAGE_SETUP) {
{
/* Read IAP Part Number Identification */ /* Read IAP Part Number Identification */
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_PART_ID_NO; iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_PART_ID_NO;
iap_cmd_call(&iap_cmd_res); iap_cmd_call(&iap_cmd_res);
if(iap_cmd_res.status_res.status_ret != CMD_SUCCESS) if (iap_cmd_res.status_res.status_ret != CMD_SUCCESS) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
}
read_partid_serialno.part_id[0] = iap_cmd_res.status_res.iap_result[0]; 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_partid_serialno.part_id[1] = iap_cmd_res.status_res.iap_result[1];
@ -77,8 +91,9 @@ usb_request_status_t usb_vendor_request_read_partid_serialno(
/* Read IAP Serial Number Identification */ /* Read IAP Serial Number Identification */
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO; iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO;
iap_cmd_call(&iap_cmd_res); iap_cmd_call(&iap_cmd_res);
if(iap_cmd_res.status_res.status_ret != CMD_SUCCESS) if (iap_cmd_res.status_res.status_ret != CMD_SUCCESS) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
}
read_partid_serialno.serial_no[0] = iap_cmd_res.status_res.iap_result[0]; 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[1] = iap_cmd_res.status_res.iap_result[1];
@ -86,15 +101,20 @@ usb_request_status_t usb_vendor_request_read_partid_serialno(
read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3]; read_partid_serialno.serial_no[3] = iap_cmd_res.status_res.iap_result[3];
length = (uint8_t) sizeof(read_partid_serialno_t); length = (uint8_t) sizeof(read_partid_serialno_t);
usb_transfer_schedule_block(endpoint->in, &read_partid_serialno, length, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
&read_partid_serialno,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
} }
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
usb_request_status_t usb_vendor_request_reset( usb_request_status_t usb_vendor_request_reset(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
wwdt_reset(100000); wwdt_reset(100000);

View File

@ -34,12 +34,16 @@ typedef struct {
} read_partid_serialno_t; } read_partid_serialno_t;
usb_request_status_t usb_vendor_request_read_board_id( usb_request_status_t usb_vendor_request_read_board_id(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_version_string( usb_request_status_t usb_vendor_request_read_version_string(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_partid_serialno( usb_request_status_t usb_vendor_request_read_partid_serialno(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_reset( usb_request_status_t usb_vendor_request_reset(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_BOARD_INFO_H__ */ #endif /* end of include guard: __USB_API_BOARD_INFO_H__ */

View File

@ -52,11 +52,10 @@ static void refill_cpld_buffer(void)
cpld_xsvf_buffer, cpld_xsvf_buffer,
sizeof(cpld_xsvf_buffer), sizeof(cpld_xsvf_buffer),
cpld_buffer_refilled, cpld_buffer_refilled,
NULL NULL);
);
// Wait until transfer finishes // Wait until transfer finishes
while (cpld_wait); while (cpld_wait) {}
} }
void cpld_update(void) void cpld_update(void)
@ -68,30 +67,33 @@ void cpld_update(void)
refill_cpld_buffer(); refill_cpld_buffer();
error = cpld_jtag_program(&jtag_cpld, sizeof(cpld_xsvf_buffer), error = cpld_jtag_program(
&jtag_cpld,
sizeof(cpld_xsvf_buffer),
cpld_xsvf_buffer, cpld_xsvf_buffer,
refill_cpld_buffer); refill_cpld_buffer);
if(error == 0) if (error == 0) {
{
halt_and_flash(6000000); halt_and_flash(6000000);
}else } else {
{
/* LED3 (Red) steady on error */ /* LED3 (Red) steady on error */
led_on(LED3); led_on(LED3);
while (1); while (1) {}
} }
} }
usb_request_status_t usb_vendor_request_cpld_checksum( usb_request_status_t usb_vendor_request_cpld_checksum(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
static uint32_t cpld_crc; static uint32_t cpld_crc;
uint8_t length; uint8_t length;
if (stage == USB_TRANSFER_STAGE_SETUP) if (stage == USB_TRANSFER_STAGE_SETUP) {
{
cpld_jtag_take(&jtag_cpld); cpld_jtag_take(&jtag_cpld);
const bool checksum_success = cpld_xc2c64a_jtag_checksum(&jtag_cpld, &cpld_hackrf_verify, &cpld_crc); const bool checksum_success = cpld_xc2c64a_jtag_checksum(
&jtag_cpld,
&cpld_hackrf_verify,
&cpld_crc);
cpld_jtag_release(&jtag_cpld); cpld_jtag_release(&jtag_cpld);
if (!checksum_success) { if (!checksum_success) {
@ -100,8 +102,12 @@ usb_request_status_t usb_vendor_request_cpld_checksum(
length = (uint8_t) sizeof(cpld_crc); length = (uint8_t) sizeof(cpld_crc);
memcpy(endpoint->buffer, &cpld_crc, length); memcpy(endpoint->buffer, &cpld_crc, length);
usb_transfer_schedule_block(endpoint->in, endpoint->buffer, length, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
endpoint->buffer,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
} }
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;

View File

@ -31,6 +31,7 @@
void cpld_update(void); void cpld_update(void);
usb_request_status_t usb_vendor_request_cpld_checksum( usb_request_status_t usb_vendor_request_cpld_checksum(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_CPLD_H__ */ #endif /* end of include guard: __USB_API_CPLD_H__ */

View File

@ -38,20 +38,20 @@ void m0_set_mode(enum m0_mode mode)
SGPIO_SET_STATUS_1 = (1 << SGPIO_SLICE_A); SGPIO_SET_STATUS_1 = (1 << SGPIO_SLICE_A);
// Wait for M0 to acknowledge by clearing the flag. // Wait for M0 to acknowledge by clearing the flag.
while (m0_state.requested_mode & M0_REQUEST_FLAG); while (m0_state.requested_mode & M0_REQUEST_FLAG) {}
} }
usb_request_status_t usb_vendor_request_get_m0_state( usb_request_status_t usb_vendor_request_get_m0_state(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) {
if( stage == USB_TRANSFER_STAGE_SETUP )
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block( usb_transfer_schedule_block(
endpoint->in, endpoint->in,
(void*) &m0_state, (void*) &m0_state,
sizeof(m0_state), sizeof(m0_state),
NULL, NULL); NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else { } else {

View File

@ -63,6 +63,7 @@ extern volatile struct m0_state m0_state;
void m0_set_mode(enum m0_mode mode); void m0_set_mode(enum m0_mode mode);
usb_request_status_t usb_vendor_request_get_m0_state( usb_request_status_t usb_vendor_request_get_m0_state(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
#endif /*__M0_STATE_H__*/ #endif /*__M0_STATE_H__*/

View File

@ -28,7 +28,8 @@
#include <sct.h> #include <sct.h>
usb_request_status_t usb_vendor_request_operacake_get_boards( usb_request_status_t usb_vendor_request_operacake_get_boards(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
operacake_get_boards(endpoint->buffer); operacake_get_boards(endpoint->buffer);
@ -39,7 +40,8 @@ usb_request_status_t usb_vendor_request_operacake_get_boards(
} }
usb_request_status_t usb_vendor_request_operacake_set_ports( usb_request_status_t usb_vendor_request_operacake_set_ports(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint8_t address, port_a, port_b; uint8_t address, port_a, port_b;
address = endpoint->setup.value & 0xFF; address = endpoint->setup.value & 0xFF;
@ -53,8 +55,10 @@ usb_request_status_t usb_vendor_request_operacake_set_ports(
} }
static unsigned char data[MAX_OPERACAKE_RANGES * 5]; static unsigned char data[MAX_OPERACAKE_RANGES * 5];
usb_request_status_t usb_vendor_request_operacake_set_ranges( usb_request_status_t usb_vendor_request_operacake_set_ranges(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint16_t i, freq_min, freq_max, num_ranges = 0; uint16_t i, freq_min, freq_max, num_ranges = 0;
uint8_t port; uint8_t port;
@ -65,10 +69,13 @@ usb_request_status_t usb_vendor_request_operacake_set_ranges(
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} }
operacake_clear_ranges(); operacake_clear_ranges();
usb_transfer_schedule_block(endpoint->out, &data, usb_transfer_schedule_block(
endpoint->setup.length, NULL, NULL); endpoint->out,
&data,
endpoint->setup.length,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) { } else if (stage == USB_TRANSFER_STAGE_DATA) {
for (i = 0; i < endpoint->setup.length; i += 5) { for (i = 0; i < endpoint->setup.length; i += 5) {
freq_min = data[i] << 8 | data[i + 1]; freq_min = data[i] << 8 | data[i + 1];
freq_max = data[i + 2] << 8 | data[i + 3]; freq_max = data[i + 2] << 8 | data[i + 3];
@ -81,7 +88,8 @@ usb_request_status_t usb_vendor_request_operacake_set_ranges(
} }
usb_request_status_t usb_vendor_request_operacake_gpio_test( usb_request_status_t usb_vendor_request_operacake_gpio_test(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint16_t test_result; uint16_t test_result;
uint8_t address = endpoint->setup.value & 0xFF; uint8_t address = endpoint->setup.value & 0xFF;
@ -89,14 +97,20 @@ usb_request_status_t usb_vendor_request_operacake_gpio_test(
test_result = gpio_test(address); test_result = gpio_test(address);
endpoint->buffer[0] = test_result & 0xff; endpoint->buffer[0] = test_result & 0xff;
endpoint->buffer[1] = test_result >> 8; endpoint->buffer[1] = test_result >> 8;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, NULL, NULL); usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
2,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
} }
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
usb_request_status_t usb_vendor_request_operacake_set_mode( usb_request_status_t usb_vendor_request_operacake_set_mode(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint8_t address, mode; uint8_t address, mode;
address = endpoint->setup.value & 0xFF; address = endpoint->setup.value & 0xFF;
@ -109,7 +123,8 @@ usb_request_status_t usb_vendor_request_operacake_set_mode(
} }
usb_request_status_t usb_vendor_request_operacake_get_mode( usb_request_status_t usb_vendor_request_operacake_get_mode(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint8_t address; uint8_t address;
address = endpoint->setup.value & 0xFF; address = endpoint->setup.value & 0xFF;
@ -122,8 +137,10 @@ usb_request_status_t usb_vendor_request_operacake_get_mode(
} }
static struct operacake_dwell_times dwell_times[SCT_EVENT_COUNT]; static struct operacake_dwell_times dwell_times[SCT_EVENT_COUNT];
usb_request_status_t usb_vendor_request_operacake_set_dwell_times( usb_request_status_t usb_vendor_request_operacake_set_dwell_times(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint16_t count; uint16_t count;
uint32_t dwell; uint32_t dwell;
@ -134,13 +151,18 @@ usb_request_status_t usb_vendor_request_operacake_set_dwell_times(
if ((count == 0) || (count > SCT_EVENT_COUNT)) { if ((count == 0) || (count > SCT_EVENT_COUNT)) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} }
usb_transfer_schedule_block(endpoint->out, &data, usb_transfer_schedule_block(
endpoint->setup.length, NULL, NULL); endpoint->out,
&data,
endpoint->setup.length,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) { } else if (stage == USB_TRANSFER_STAGE_DATA) {
count = endpoint->setup.length / 5; count = endpoint->setup.length / 5;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
dwell = data[(i*5)+0] | (data[(i*5)+1] << 8) | (data[(i*5)+2] << 16) | (data[(i*5)+3] << 24); dwell = data[(i * 5) + 0] | (data[(i * 5) + 1] << 8) |
(data[(i * 5) + 2] << 16) | (data[(i * 5) + 3] << 24);
port = data[(i * 5) + 4]; port = data[(i * 5) + 4];
dwell_times[i].dwell = dwell; dwell_times[i].dwell = dwell;
dwell_times[i].port = port; dwell_times[i].port = port;

View File

@ -26,24 +26,31 @@
#include <usb_request.h> #include <usb_request.h>
usb_request_status_t usb_vendor_request_operacake_get_boards( usb_request_status_t usb_vendor_request_operacake_get_boards(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_set_ports( usb_request_status_t usb_vendor_request_operacake_set_ports(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_set_ranges( usb_request_status_t usb_vendor_request_operacake_set_ranges(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_gpio_test( usb_request_status_t usb_vendor_request_operacake_gpio_test(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_set_mode( usb_request_status_t usb_vendor_request_operacake_set_mode(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_get_mode( usb_request_status_t usb_vendor_request_operacake_get_mode(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_set_dwell_times( usb_request_status_t usb_vendor_request_operacake_set_dwell_times(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_OPERACAKE_H__ */ #endif /* end of include guard: __USB_API_OPERACAKE_H__ */

View File

@ -34,12 +34,15 @@
usb_request_status_t usb_vendor_request_write_max2837( usb_request_status_t usb_vendor_request_write_max2837(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
if (endpoint->setup.index < MAX2837_NUM_REGS) { if (endpoint->setup.index < MAX2837_NUM_REGS) {
if (endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE) { if (endpoint->setup.value < MAX2837_DATA_REGS_MAX_VALUE) {
max2837_reg_write(&max2837, endpoint->setup.index, endpoint->setup.value); max2837_reg_write(
&max2837,
endpoint->setup.index,
endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -52,15 +55,20 @@ usb_request_status_t usb_vendor_request_write_max2837(
usb_request_status_t usb_vendor_request_read_max2837( usb_request_status_t usb_vendor_request_read_max2837(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
if (endpoint->setup.index < MAX2837_NUM_REGS) { if (endpoint->setup.index < MAX2837_NUM_REGS) {
const uint16_t value = max2837_reg_read(&max2837, endpoint->setup.index); const uint16_t value =
max2837_reg_read(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value & 0xff; endpoint->buffer[0] = value & 0xff;
endpoint->buffer[1] = value >> 8; endpoint->buffer[1] = value >> 8;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
&endpoint->buffer,
2,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -72,12 +80,15 @@ usb_request_status_t usb_vendor_request_read_max2837(
usb_request_status_t usb_vendor_request_write_si5351c( usb_request_status_t usb_vendor_request_write_si5351c(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
if (endpoint->setup.index < 256) { if (endpoint->setup.index < 256) {
if (endpoint->setup.value < 256) { if (endpoint->setup.value < 256) {
si5351c_write_single(&clock_gen, endpoint->setup.index, endpoint->setup.value); si5351c_write_single(
&clock_gen,
endpoint->setup.index,
endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -90,14 +101,19 @@ usb_request_status_t usb_vendor_request_write_si5351c(
usb_request_status_t usb_vendor_request_read_si5351c( usb_request_status_t usb_vendor_request_read_si5351c(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
if (endpoint->setup.index < 256) { if (endpoint->setup.index < 256) {
const uint8_t value = si5351c_read_single(&clock_gen, endpoint->setup.index); const uint8_t value =
si5351c_read_single(&clock_gen, endpoint->setup.index);
endpoint->buffer[0] = value; endpoint->buffer[0] = value;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -110,13 +126,14 @@ usb_request_status_t usb_vendor_request_read_si5351c(
#ifndef RAD1O #ifndef RAD1O
usb_request_status_t usb_vendor_request_write_rffc5071( usb_request_status_t usb_vendor_request_write_rffc5071(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) {
if( stage == USB_TRANSFER_STAGE_SETUP )
{ {
if( endpoint->setup.index < RFFC5071_NUM_REGS ) if (stage == USB_TRANSFER_STAGE_SETUP) {
{ if (endpoint->setup.index < RFFC5071_NUM_REGS) {
rffc5071_reg_write(&mixer, endpoint->setup.index, endpoint->setup.value); rffc5071_reg_write(
&mixer,
endpoint->setup.index,
endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -128,18 +145,20 @@ usb_request_status_t usb_vendor_request_write_rffc5071(
usb_request_status_t usb_vendor_request_read_rffc5071( usb_request_status_t usb_vendor_request_read_rffc5071(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
uint16_t value; uint16_t value;
if( stage == USB_TRANSFER_STAGE_SETUP ) if (stage == USB_TRANSFER_STAGE_SETUP) {
{ if (endpoint->setup.index < RFFC5071_NUM_REGS) {
if( endpoint->setup.index < RFFC5071_NUM_REGS )
{
value = rffc5071_reg_read(&mixer, endpoint->setup.index); value = rffc5071_reg_read(&mixer, endpoint->setup.index);
endpoint->buffer[0] = value & 0xff; endpoint->buffer[0] = value & 0xff;
endpoint->buffer[1] = value >> 8; endpoint->buffer[1] = value >> 8;
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
&endpoint->buffer,
2,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -152,8 +171,8 @@ usb_request_status_t usb_vendor_request_read_rffc5071(
usb_request_status_t usb_vendor_request_set_clkout_enable( usb_request_status_t usb_vendor_request_set_clkout_enable(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
si5351c_clkout_enable(&clock_gen, endpoint->setup.value); si5351c_clkout_enable(&clock_gen, endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);

View File

@ -28,31 +28,24 @@
usb_request_status_t usb_vendor_request_write_max2837( usb_request_status_t usb_vendor_request_write_max2837(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_vendor_request_read_max2837( usb_request_status_t usb_vendor_request_read_max2837(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_vendor_request_write_si5351c( usb_request_status_t usb_vendor_request_write_si5351c(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_vendor_request_read_si5351c( usb_request_status_t usb_vendor_request_read_si5351c(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_vendor_request_write_rffc5071( usb_request_status_t usb_vendor_request_write_rffc5071(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_vendor_request_read_rffc5071( usb_request_status_t usb_vendor_request_read_rffc5071(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
usb_request_status_t usb_vendor_request_set_clkout_enable( usb_request_status_t usb_vendor_request_set_clkout_enable(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
#endif /* end of include guard: __USB_API_REGISTER_H__ */ #endif /* end of include guard: __USB_API_REGISTER_H__ */

View File

@ -34,7 +34,8 @@
uint8_t spiflash_buffer[256U]; uint8_t spiflash_buffer[256U];
usb_request_status_t usb_vendor_request_erase_spiflash( usb_request_status_t usb_vendor_request_erase_spiflash(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
@ -47,7 +48,8 @@ usb_request_status_t usb_vendor_request_erase_spiflash(
} }
usb_request_status_t usb_vendor_request_write_spiflash( usb_request_status_t usb_vendor_request_write_spiflash(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint32_t addr = 0; uint32_t addr = 0;
uint16_t len = 0; uint16_t len = 0;
@ -55,12 +57,16 @@ usb_request_status_t usb_vendor_request_write_spiflash(
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
addr = (endpoint->setup.value << 16) | endpoint->setup.index; addr = (endpoint->setup.value << 16) | endpoint->setup.index;
len = endpoint->setup.length; len = endpoint->setup.length;
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) ||
|| ((addr + len) > spi_flash.num_bytes)) { ((addr + len) > spi_flash.num_bytes)) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} else { } else {
usb_transfer_schedule_block(endpoint->out, &spiflash_buffer[0], len, usb_transfer_schedule_block(
NULL, NULL); endpoint->out,
&spiflash_buffer[0],
len,
NULL,
NULL);
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv); spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
w25q80bv_setup(&spi_flash); w25q80bv_setup(&spi_flash);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
@ -69,8 +75,8 @@ usb_request_status_t usb_vendor_request_write_spiflash(
addr = (endpoint->setup.value << 16) | endpoint->setup.index; addr = (endpoint->setup.value << 16) | endpoint->setup.index;
len = endpoint->setup.length; len = endpoint->setup.length;
/* This check is redundant but makes me feel better. */ /* This check is redundant but makes me feel better. */
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) ||
|| ((addr + len) > spi_flash.num_bytes)) { ((addr + len) > spi_flash.num_bytes)) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} else { } else {
w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]); w25q80bv_program(&spi_flash, addr, len, &spiflash_buffer[0]);
@ -83,50 +89,56 @@ usb_request_status_t usb_vendor_request_write_spiflash(
} }
usb_request_status_t usb_vendor_request_read_spiflash( usb_request_status_t usb_vendor_request_read_spiflash(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint32_t addr; uint32_t addr;
uint16_t len; uint16_t len;
if (stage == USB_TRANSFER_STAGE_SETUP) if (stage == USB_TRANSFER_STAGE_SETUP) {
{
addr = (endpoint->setup.value << 16) | endpoint->setup.index; addr = (endpoint->setup.value << 16) | endpoint->setup.index;
len = endpoint->setup.length; len = endpoint->setup.length;
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) ||
|| ((addr + len) > spi_flash.num_bytes)) { ((addr + len) > spi_flash.num_bytes)) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} else { } else {
w25q80bv_read(&spi_flash, addr, len, &spiflash_buffer[0]); w25q80bv_read(&spi_flash, addr, len, &spiflash_buffer[0]);
usb_transfer_schedule_block(endpoint->in, &spiflash_buffer[0], len, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
&spiflash_buffer[0],
len,
NULL,
NULL);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
} else if (stage == USB_TRANSFER_STAGE_DATA) } else if (stage == USB_TRANSFER_STAGE_DATA) {
{
addr = (endpoint->setup.value << 16) | endpoint->setup.index; addr = (endpoint->setup.value << 16) | endpoint->setup.index;
len = endpoint->setup.length; len = endpoint->setup.length;
/* This check is redundant but makes me feel better. */ /* This check is redundant but makes me feel better. */
if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) if ((len > spi_flash.page_len) || (addr > spi_flash.num_bytes) ||
|| ((addr + len) > spi_flash.num_bytes)) ((addr + len) > spi_flash.num_bytes)) {
{
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} else } else {
{
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
} else } else {
{
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
} }
usb_request_status_t usb_vendor_request_spiflash_status( usb_request_status_t usb_vendor_request_spiflash_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
w25q80bv_get_full_status(&spi_flash, endpoint->buffer); w25q80bv_get_full_status(&spi_flash, endpoint->buffer);
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 2, NULL, NULL); usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
2,
NULL,
NULL);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA) { } else if (stage == USB_TRANSFER_STAGE_DATA) {
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
@ -137,7 +149,8 @@ usb_request_status_t usb_vendor_request_spiflash_status(
} }
usb_request_status_t usb_vendor_request_spiflash_clear_status( usb_request_status_t usb_vendor_request_spiflash_clear_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
w25q80bv_clear_status(&spi_flash); w25q80bv_clear_status(&spi_flash);

View File

@ -27,14 +27,19 @@
#include <usb_request.h> #include <usb_request.h>
usb_request_status_t usb_vendor_request_erase_spiflash( usb_request_status_t usb_vendor_request_erase_spiflash(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_write_spiflash( usb_request_status_t usb_vendor_request_write_spiflash(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_read_spiflash( usb_request_status_t usb_vendor_request_read_spiflash(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_spiflash_status( usb_request_status_t usb_vendor_request_spiflash_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_spiflash_clear_status( usb_request_status_t usb_vendor_request_spiflash_clear_status(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
#endif /* end of include guard: __USB_API_SPIFLASH_H__ */ #endif /* end of include guard: __USB_API_SPIFLASH_H__ */

View File

@ -49,7 +49,8 @@ static enum sweep_style style = LINEAR;
/* Do this before starting sweep mode with request_transceiver_mode(). */ /* Do this before starting sweep mode with request_transceiver_mode(). */
usb_request_status_t usb_vendor_request_init_sweep( usb_request_status_t usb_vendor_request_init_sweep(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
uint32_t num_bytes; uint32_t num_bytes;
int i; int i;
@ -63,22 +64,27 @@ usb_request_status_t usb_vendor_request_init_sweep(
if ((1 > num_ranges) || (MAX_RANGES < num_ranges)) { if ((1 > num_ranges) || (MAX_RANGES < num_ranges)) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} }
usb_transfer_schedule_block(endpoint->out, &data, usb_transfer_schedule_block(
endpoint->setup.length, NULL, NULL); endpoint->out,
&data,
endpoint->setup.length,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) { } else if (stage == USB_TRANSFER_STAGE_DATA) {
step_width = ((uint32_t)(data[3]) << 24) | ((uint32_t)(data[2]) << 16) step_width = ((uint32_t) (data[3]) << 24) | ((uint32_t) (data[2]) << 16) |
| ((uint32_t)(data[1]) << 8) | data[0]; ((uint32_t) (data[1]) << 8) | data[0];
if (1 > step_width) { if (1 > step_width) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} }
offset = ((uint32_t)(data[7]) << 24) | ((uint32_t)(data[6]) << 16) offset = ((uint32_t) (data[7]) << 24) | ((uint32_t) (data[6]) << 16) |
| ((uint32_t)(data[5]) << 8) | data[4]; ((uint32_t) (data[5]) << 8) | data[4];
style = data[8]; style = data[8];
if (INTERLEAVED < style) { if (INTERLEAVED < style) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} }
for (i = 0; i < (num_ranges * 2); i++) { for (i = 0; i < (num_ranges * 2); i++) {
frequencies[i] = ((uint16_t)(data[10+i*2]) << 8) + data[9+i*2]; frequencies[i] =
((uint16_t) (data[10 + i * 2]) << 8) + data[9 + i * 2];
} }
sweep_freq = (uint64_t) frequencies[0] * FREQ_GRANULARITY; sweep_freq = (uint64_t) frequencies[0] * FREQ_GRANULARITY;
set_freq(sweep_freq + offset); set_freq(sweep_freq + offset);
@ -97,7 +103,8 @@ void sweep_bulk_transfer_complete(void *user_data, unsigned int bytes_transferre
m0_state.m4_count += 3 * 0x4000; m0_state.m4_count += 3 * 0x4000;
} }
void sweep_mode(uint32_t seq) { void sweep_mode(uint32_t seq)
{
// Sweep mode is implemented using timed M0 operations, as follows: // Sweep mode is implemented using timed M0 operations, as follows:
// //
// 0. M4 initially puts the M0 into RX mode, with an m0_count threshold // 0. M4 initially puts the M0 into RX mode, with an m0_count threshold
@ -137,11 +144,12 @@ void sweep_mode(uint32_t seq) {
baseband_streaming_enable(&sgpio_config); baseband_streaming_enable(&sgpio_config);
while (transceiver_request.seq == seq) { while (transceiver_request.seq == seq) {
// Wait for M0 to finish receiving a buffer. // Wait for M0 to finish receiving a buffer.
while (m0_state.active_mode != M0_MODE_WAIT) while (m0_state.active_mode != M0_MODE_WAIT) {
if (transceiver_request.seq != seq) if (transceiver_request.seq != seq) {
goto end; goto end;
}
}
// Set M0 to switch back to RX after two more buffers. // Set M0 to switch back to RX after two more buffers.
m0_state.threshold += 0x8000; m0_state.threshold += 0x8000;
@ -165,8 +173,8 @@ void sweep_mode(uint32_t seq) {
&usb_endpoint_bulk_in, &usb_endpoint_bulk_in,
buffer, buffer,
0x4000, 0x4000,
sweep_bulk_transfer_complete, NULL sweep_bulk_transfer_complete,
); NULL);
// Use other buffer next time. // Use other buffer next time.
phase = (phase + 1) % 2; phase = (phase + 1) % 2;
@ -174,9 +182,13 @@ void sweep_mode(uint32_t seq) {
if (++blocks_queued == dwell_blocks) { if (++blocks_queued == dwell_blocks) {
// Calculate next sweep frequency. // Calculate next sweep frequency.
if (INTERLEAVED == style) { if (INTERLEAVED == style) {
if(!odd && ((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY))) { if (!odd &&
((sweep_freq + step_width) >=
((uint64_t) frequencies[1 + range * 2] *
FREQ_GRANULARITY))) {
range = (range + 1) % num_ranges; range = (range + 1) % num_ranges;
sweep_freq = (uint64_t)frequencies[range*2] * FREQ_GRANULARITY; sweep_freq = (uint64_t) frequencies[range * 2] *
FREQ_GRANULARITY;
} else { } else {
if (odd) { if (odd) {
sweep_freq += step_width / 4; sweep_freq += step_width / 4;
@ -186,9 +198,12 @@ void sweep_mode(uint32_t seq) {
} }
odd = !odd; odd = !odd;
} else { } else {
if((sweep_freq + step_width) >= ((uint64_t)frequencies[1+range*2] * FREQ_GRANULARITY)) { if ((sweep_freq + step_width) >=
((uint64_t) frequencies[1 + range * 2] *
FREQ_GRANULARITY)) {
range = (range + 1) % num_ranges; range = (range + 1) % num_ranges;
sweep_freq = (uint64_t)frequencies[range*2] * FREQ_GRANULARITY; sweep_freq = (uint64_t) frequencies[range * 2] *
FREQ_GRANULARITY;
} else { } else {
sweep_freq += step_width; sweep_freq += step_width;
} }
@ -201,9 +216,11 @@ void sweep_mode(uint32_t seq) {
} }
// Wait for M0 to resume RX. // Wait for M0 to resume RX.
while (m0_state.active_mode != M0_MODE_RX) while (m0_state.active_mode != M0_MODE_RX) {
if (transceiver_request.seq != seq) if (transceiver_request.seq != seq) {
goto end; goto end;
}
}
// Set M0 to switch back to WAIT after filling next buffer. // Set M0 to switch back to WAIT after filling next buffer.
m0_state.threshold += 0x4000; m0_state.threshold += 0x4000;

View File

@ -32,7 +32,8 @@ enum sweep_style {
}; };
usb_request_status_t usb_vendor_request_init_sweep( usb_request_status_t usb_vendor_request_init_sweep(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
void sweep_mode(uint32_t seq); void sweep_mode(uint32_t seq);

View File

@ -70,10 +70,11 @@ set_sample_r_params_t set_sample_r_params;
usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth( usb_request_status_t usb_vendor_request_set_baseband_filter_bandwidth(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
const uint32_t bandwidth = (endpoint->setup.index << 16) | endpoint->setup.value; const uint32_t bandwidth =
(endpoint->setup.index << 16) | endpoint->setup.value;
if (baseband_filter_bandwidth_set(bandwidth)) { if (baseband_filter_bandwidth_set(bandwidth)) {
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
@ -88,22 +89,23 @@ usb_request_status_t usb_vendor_request_set_freq(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) if (stage == USB_TRANSFER_STAGE_SETUP) {
{ usb_transfer_schedule_block(
usb_transfer_schedule_block(endpoint->out, &set_freq_params, sizeof(set_freq_params_t), endpoint->out,
NULL, NULL); &set_freq_params,
sizeof(set_freq_params_t),
NULL,
NULL);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA) } else if (stage == USB_TRANSFER_STAGE_DATA) {
{ const uint64_t freq =
const uint64_t freq = set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz; set_freq_params.freq_mhz * 1000000ULL + set_freq_params.freq_hz;
if( set_freq(freq) ) if (set_freq(freq)) {
{
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} else } else {
{
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
} }
@ -112,27 +114,30 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage) const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) if (stage == USB_TRANSFER_STAGE_SETUP) {
{ usb_transfer_schedule_block(
usb_transfer_schedule_block(endpoint->out, &set_sample_r_params, sizeof(set_sample_r_params_t), endpoint->out,
NULL, NULL); &set_sample_r_params,
sizeof(set_sample_r_params_t),
NULL,
NULL);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA) } else if (stage == USB_TRANSFER_STAGE_DATA) {
{ if (sample_rate_frac_set(
if( sample_rate_frac_set(set_sample_r_params.freq_hz * 2, set_sample_r_params.divider ) ) set_sample_r_params.freq_hz * 2,
{ set_sample_r_params.divider)) {
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} else } else {
{
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
} }
usb_request_status_t usb_vendor_request_set_amp_enable( usb_request_status_t usb_vendor_request_set_amp_enable(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
switch (endpoint->setup.value) { switch (endpoint->setup.value) {
@ -157,11 +162,18 @@ usb_request_status_t usb_vendor_request_set_lna_gain(
const usb_transfer_stage_t stage) const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
const uint8_t value = max2837_set_lna_gain(&max2837, endpoint->setup.index); const uint8_t value =
max2837_set_lna_gain(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value; endpoint->buffer[0] = value;
if(value) hackrf_ui()->set_bb_lna_gain(endpoint->setup.index); if (value) {
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, hackrf_ui()->set_bb_lna_gain(endpoint->setup.index);
NULL, NULL); }
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -169,14 +181,22 @@ usb_request_status_t usb_vendor_request_set_lna_gain(
} }
usb_request_status_t usb_vendor_request_set_vga_gain( usb_request_status_t usb_vendor_request_set_vga_gain(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
const uint8_t value = max2837_set_vga_gain(&max2837, endpoint->setup.index); const uint8_t value =
max2837_set_vga_gain(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value; endpoint->buffer[0] = value;
if(value) hackrf_ui()->set_bb_vga_gain(endpoint->setup.index); if (value) {
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, hackrf_ui()->set_bb_vga_gain(endpoint->setup.index);
NULL, NULL); }
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -184,14 +204,22 @@ usb_request_status_t usb_vendor_request_set_vga_gain(
} }
usb_request_status_t usb_vendor_request_set_txvga_gain( usb_request_status_t usb_vendor_request_set_txvga_gain(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
const uint8_t value = max2837_set_txvga_gain(&max2837, endpoint->setup.index); const uint8_t value =
max2837_set_txvga_gain(&max2837, endpoint->setup.index);
endpoint->buffer[0] = value; endpoint->buffer[0] = value;
if(value) hackrf_ui()->set_bb_tx_vga_gain(endpoint->setup.index); if (value) {
usb_transfer_schedule_block(endpoint->in, &endpoint->buffer, 1, hackrf_ui()->set_bb_tx_vga_gain(endpoint->setup.index);
NULL, NULL); }
usb_transfer_schedule_block(
endpoint->in,
&endpoint->buffer,
1,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -199,7 +227,8 @@ usb_request_status_t usb_vendor_request_set_txvga_gain(
} }
usb_request_status_t usb_vendor_request_set_antenna_enable( usb_request_status_t usb_vendor_request_set_antenna_enable(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
switch (endpoint->setup.value) { switch (endpoint->setup.value) {
@ -224,12 +253,18 @@ usb_request_status_t usb_vendor_request_set_freq_explicit(
const usb_transfer_stage_t stage) const usb_transfer_stage_t stage)
{ {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(endpoint->out, &explicit_params, usb_transfer_schedule_block(
sizeof(struct set_freq_explicit_params), NULL, NULL); endpoint->out,
&explicit_params,
sizeof(struct set_freq_explicit_params),
NULL,
NULL);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else if (stage == USB_TRANSFER_STAGE_DATA) { } else if (stage == USB_TRANSFER_STAGE_DATA) {
if (set_freq_explicit(explicit_params.if_freq_hz, if (set_freq_explicit(
explicit_params.lo_freq_hz, explicit_params.path)) { explicit_params.if_freq_hz,
explicit_params.lo_freq_hz,
explicit_params.path)) {
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} }
@ -243,7 +278,8 @@ static volatile hw_sync_mode_t _hw_sync_mode = HW_SYNC_MODE_OFF;
static volatile uint32_t _tx_underrun_limit; static volatile uint32_t _tx_underrun_limit;
static volatile uint32_t _rx_overrun_limit; static volatile uint32_t _rx_overrun_limit;
void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode) { void set_hw_sync_mode(const hw_sync_mode_t new_hw_sync_mode)
{
_hw_sync_mode = new_hw_sync_mode; _hw_sync_mode = new_hw_sync_mode;
} }
@ -276,8 +312,8 @@ void transceiver_shutdown(void)
m0_set_mode(M0_MODE_IDLE); m0_set_mode(M0_MODE_IDLE);
} }
void transceiver_startup(const transceiver_mode_t mode) { void transceiver_startup(const transceiver_mode_t mode)
{
hackrf_ui()->set_transceiver_mode(mode); hackrf_ui()->set_transceiver_mode(mode);
switch (mode) { switch (mode) {
@ -341,8 +377,8 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode(
usb_request_status_t usb_vendor_request_set_tx_underrun_limit( usb_request_status_t usb_vendor_request_set_tx_underrun_limit(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value; uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value;
_tx_underrun_limit = value; _tx_underrun_limit = value;
@ -353,8 +389,8 @@ usb_request_status_t usb_vendor_request_set_tx_underrun_limit(
usb_request_status_t usb_vendor_request_set_rx_overrun_limit( usb_request_status_t usb_vendor_request_set_rx_overrun_limit(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value; uint32_t value = (endpoint->setup.index << 16) + endpoint->setup.value;
_rx_overrun_limit = value; _rx_overrun_limit = value;
@ -369,7 +405,8 @@ void transceiver_bulk_transfer_complete(void *user_data, unsigned int bytes_tran
m0_state.m4_count += bytes_transferred; m0_state.m4_count += bytes_transferred;
} }
void rx_mode(uint32_t seq) { void rx_mode(uint32_t seq)
{
uint32_t usb_count = 0; uint32_t usb_count = 0;
transceiver_startup(TRANSCEIVER_MODE_RX); transceiver_startup(TRANSCEIVER_MODE_RX);
@ -383,8 +420,7 @@ void rx_mode(uint32_t seq) {
&usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK], &usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK],
USB_TRANSFER_SIZE, USB_TRANSFER_SIZE,
transceiver_bulk_transfer_complete, transceiver_bulk_transfer_complete,
NULL NULL);
);
usb_count += USB_TRANSFER_SIZE; usb_count += USB_TRANSFER_SIZE;
} }
} }
@ -392,7 +428,8 @@ void rx_mode(uint32_t seq) {
transceiver_shutdown(); transceiver_shutdown();
} }
void tx_mode(uint32_t seq) { void tx_mode(uint32_t seq)
{
unsigned int usb_count = 0; unsigned int usb_count = 0;
transceiver_startup(TRANSCEIVER_MODE_TX); transceiver_startup(TRANSCEIVER_MODE_TX);
@ -403,8 +440,7 @@ void tx_mode(uint32_t seq) {
&usb_bulk_buffer[0x0000], &usb_bulk_buffer[0x0000],
USB_TRANSFER_SIZE, USB_TRANSFER_SIZE,
transceiver_bulk_transfer_complete, transceiver_bulk_transfer_complete,
NULL NULL);
);
usb_count += USB_TRANSFER_SIZE; usb_count += USB_TRANSFER_SIZE;
// Enable streaming. The M0 is in TX_START mode, and will automatically // Enable streaming. The M0 is in TX_START mode, and will automatically
@ -420,8 +456,7 @@ void tx_mode(uint32_t seq) {
&usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK], &usb_bulk_buffer[usb_count & USB_BULK_BUFFER_MASK],
USB_TRANSFER_SIZE, USB_TRANSFER_SIZE,
transceiver_bulk_transfer_complete, transceiver_bulk_transfer_complete,
NULL NULL);
);
usb_count += USB_TRANSFER_SIZE; usb_count += USB_TRANSFER_SIZE;
} }
} }
@ -433,5 +468,5 @@ void off_mode(uint32_t seq)
{ {
hackrf_ui()->set_transceiver_mode(TRANSCEIVER_MODE_OFF); hackrf_ui()->set_transceiver_mode(TRANSCEIVER_MODE_OFF);
while (transceiver_request.seq == seq); while (transceiver_request.seq == seq) {}
} }

View File

@ -48,24 +48,32 @@ usb_request_status_t usb_vendor_request_set_sample_rate_frac(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage); const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_amp_enable( usb_request_status_t usb_vendor_request_set_amp_enable(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_lna_gain( usb_request_status_t usb_vendor_request_set_lna_gain(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage); const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_vga_gain( usb_request_status_t usb_vendor_request_set_vga_gain(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_txvga_gain( usb_request_status_t usb_vendor_request_set_txvga_gain(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_antenna_enable( usb_request_status_t usb_vendor_request_set_antenna_enable(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_freq_explicit( usb_request_status_t usb_vendor_request_set_freq_explicit(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_hw_sync_mode( usb_request_status_t usb_vendor_request_set_hw_sync_mode(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_tx_underrun_limit( usb_request_status_t usb_vendor_request_set_tx_underrun_limit(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_set_rx_overrun_limit( usb_request_status_t usb_vendor_request_set_rx_overrun_limit(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage); usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
void request_transceiver_mode(transceiver_mode_t mode); void request_transceiver_mode(transceiver_mode_t mode);
void transceiver_startup(transceiver_mode_t mode); void transceiver_startup(transceiver_mode_t mode);

View File

@ -30,8 +30,8 @@
usb_request_status_t usb_vendor_request_set_ui_enable( usb_request_status_t usb_vendor_request_set_ui_enable(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if (stage == USB_TRANSFER_STAGE_SETUP) { if (stage == USB_TRANSFER_STAGE_SETUP) {
hackrf_ui_set_enable(endpoint->setup.value); hackrf_ui_set_enable(endpoint->setup.value);
usb_transfer_schedule_ack(endpoint->in); usb_transfer_schedule_ack(endpoint->in);

View File

@ -27,7 +27,6 @@
usb_request_status_t usb_vendor_request_set_ui_enable( usb_request_status_t usb_vendor_request_set_ui_enable(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
#endif /* end of include guard: __USB_API_UI_H__ */ #endif /* end of include guard: __USB_API_UI_H__ */

View File

@ -152,13 +152,13 @@ uint8_t usb_descriptor_configuration_high_speed[] = {
0, // TERMINATOR 0, // TERMINATOR
}; };
uint8_t usb_descriptor_string_languages[] = { uint8_t usb_descriptor_string_languages[] = {
0x04, // bLength 0x04, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType
USB_WORD(USB_STRING_LANGID), // wLANGID USB_WORD(USB_STRING_LANGID), // wLANGID
}; };
// clang-format off
uint8_t usb_descriptor_string_manufacturer[] = { uint8_t usb_descriptor_string_manufacturer[] = {
40, // bLength 40, // bLength
USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType USB_DESCRIPTOR_TYPE_STRING, // bDescriptorType

View File

@ -30,7 +30,8 @@ extern uint8_t usb_descriptor_string_manufacturer[];
extern uint8_t usb_descriptor_string_product[]; extern uint8_t usb_descriptor_string_product[];
#define USB_DESCRIPTOR_STRING_SERIAL_LEN 32 #define USB_DESCRIPTOR_STRING_SERIAL_LEN 32
#define USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN (USB_DESCRIPTOR_STRING_SERIAL_LEN*2 + 2) /* UTF-16LE */ #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_string_serial_number[];
extern uint8_t* usb_descriptor_strings[]; extern uint8_t* usb_descriptor_strings[];

View File

@ -38,7 +38,6 @@ usb_configuration_t usb_configuration_full_speed = {
.descriptor = usb_descriptor_configuration_full_speed, .descriptor = usb_descriptor_configuration_full_speed,
}; };
usb_configuration_t* usb_configurations[] = { usb_configuration_t* usb_configurations[] = {
&usb_configuration_high_speed, &usb_configuration_high_speed,
&usb_configuration_full_speed, &usb_configuration_full_speed,

View File

@ -56,8 +56,7 @@ usb_endpoint_t usb_endpoint_bulk_in = {
.in = &usb_endpoint_bulk_in, .in = &usb_endpoint_bulk_in,
.out = 0, .out = 0,
.setup_complete = 0, .setup_complete = 0,
.transfer_complete = usb_queue_transfer_complete .transfer_complete = usb_queue_transfer_complete};
};
static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 1); static USB_DEFINE_QUEUE(usb_endpoint_bulk_in, 1);
usb_endpoint_t usb_endpoint_bulk_out = { usb_endpoint_t usb_endpoint_bulk_out = {
@ -66,8 +65,5 @@ usb_endpoint_t usb_endpoint_bulk_out = {
.in = 0, .in = 0,
.out = &usb_endpoint_bulk_out, .out = &usb_endpoint_bulk_out,
.setup_complete = 0, .setup_complete = 0,
.transfer_complete = usb_queue_transfer_complete .transfer_complete = usb_queue_transfer_complete};
};
static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 1); static USB_DEFINE_QUEUE(usb_endpoint_bulk_out, 1);

View File

@ -35,7 +35,8 @@ typedef int bool;
#define CLOCK_UNDEFINED 0xFF #define CLOCK_UNDEFINED 0xFF
#define REGISTER_INVALID 32767 #define REGISTER_INVALID 32767
int parse_int(char* s, uint8_t* const value) { int parse_int(char* s, uint8_t* const value)
{
uint_fast8_t base = 10; uint_fast8_t base = 10;
char* s_end; char* s_end;
long long_value; long long_value;
@ -62,14 +63,17 @@ int parse_int(char* s, uint8_t* const value) {
} }
} }
int si5351c_read_register(hackrf_device* device, const uint16_t register_number) { int si5351c_read_register(hackrf_device* device, const uint16_t register_number)
{
uint16_t register_value; uint16_t register_value;
int result = hackrf_si5351c_read(device, register_number, &register_value); int result = hackrf_si5351c_read(device, register_number, &register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("[%3d] -> 0x%02x\n", register_number, register_value); printf("[%3d] -> 0x%02x\n", register_number, register_value);
} else { } else {
printf("hackrf_si5351c_read() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_si5351c_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
@ -78,15 +82,17 @@ int si5351c_read_register(hackrf_device* device, const uint16_t register_number)
int si5351c_write_register( int si5351c_write_register(
hackrf_device* device, hackrf_device* device,
const uint16_t register_number, const uint16_t register_number,
const uint16_t register_value const uint16_t register_value)
) { {
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
result = hackrf_si5351c_write(device, register_number, register_value); result = hackrf_si5351c_write(device, register_number, register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("0x%2x -> [%3d]\n", register_value, register_number); printf("0x%2x -> [%3d]\n", register_value, register_number);
} else { } else {
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_max2837_write() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
@ -101,23 +107,28 @@ int si5351c_write_register(
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2 #define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3 #define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
void print_clk_control(uint16_t clk_ctrl) { void print_clk_control(uint16_t clk_ctrl)
{
uint8_t clk_src, clk_pwr; uint8_t clk_src, clk_pwr;
printf("\tclock control = "); printf("\tclock control = ");
if(clk_ctrl & SI5351C_CLK_POWERDOWN) if (clk_ctrl & SI5351C_CLK_POWERDOWN) {
printf("Down, "); printf("Down, ");
else } else {
printf("Up, "); printf("Up, ");
if(clk_ctrl & SI5351C_CLK_INT_MODE) }
if (clk_ctrl & SI5351C_CLK_INT_MODE) {
printf("Int Mode, "); printf("Int Mode, ");
else } else {
printf("Frac Mode, "); printf("Frac Mode, ");
if(clk_ctrl & SI5351C_CLK_PLL_SRC) }
if (clk_ctrl & SI5351C_CLK_PLL_SRC) {
printf("PLL src B, "); printf("PLL src B, ");
else } else {
printf("PLL src A, "); printf("PLL src A, ");
if(clk_ctrl & SI5351C_CLK_INV) }
if (clk_ctrl & SI5351C_CLK_INV) {
printf("Inverted, "); printf("Inverted, ");
}
clk_src = (clk_ctrl >> 2) & 0x3; clk_src = (clk_ctrl >> 2) & 0x3;
switch (clk_src) { switch (clk_src) {
case 0: case 0:
@ -150,7 +161,8 @@ void print_clk_control(uint16_t clk_ctrl) {
} }
} }
int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) { int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number)
{
uint_fast8_t i, reg_base, reg_number; uint_fast8_t i, reg_base, reg_number;
uint16_t parameters[8], clk_control; uint16_t parameters[8], clk_control;
uint32_t p1, p2, p3, r_div; uint32_t p1, p2, p3, r_div;
@ -173,22 +185,23 @@ int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_
} }
} }
p1 = ((parameters[2] & 0x03) << 16) p1 = ((parameters[2] & 0x03) << 16) | (parameters[3] << 8) |
| (parameters[3] << 8) parameters[4];
| parameters[4]; p2 = ((parameters[5] & 0x0F) << 16) | (parameters[6] << 8) |
p2 = ((parameters[5] & 0x0F) << 16) parameters[7];
| (parameters[6] << 8) p3 = ((parameters[5] & 0xF0) << 12) | (parameters[0] << 8) |
| parameters[7]; parameters[1];
p3 = ((parameters[5] & 0xF0) << 12)
| (parameters[0] << 8)
| parameters[1];
r_div = (parameters[2] >> 4) & 0x7; r_div = (parameters[2] >> 4) & 0x7;
printf("\tp1 = %u\n", p1); printf("\tp1 = %u\n", p1);
printf("\tp2 = %u\n", p2); printf("\tp2 = %u\n", p2);
printf("\tp3 = %u\n", p3); printf("\tp3 = %u\n", p3);
if(p3) if (p3) {
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", ((double)800 / (double)(((double)p1*p3 + p2 + 512*p3)/(double)(128*p3))) / div_lut[r_div] ); printf("\tOutput (800Mhz PLL): %#.10f Mhz\n",
((double) 800 /
(double) (((double) p1 * p3 + p2 + 512 * p3) / (double) (128 * p3))) /
div_lut[r_div]);
}
} else { } else {
// MS6 and 7 are integer only // MS6 and 7 are integer only
unsigned int parms; unsigned int parms;
@ -196,22 +209,27 @@ int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
uint_fast8_t reg_number = reg_base + i; uint_fast8_t reg_number = reg_base + i;
int result = hackrf_si5351c_read(device, reg_number, &parameters[i]); int result =
hackrf_si5351c_read(device, reg_number, &parameters[i]);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
return result; return result;
} }
} }
r_div = (ms_number == 6) ? parameters[2] & 0x7 : (parameters[2] & 0x70) >> 4 ; r_div = (ms_number == 6) ? parameters[2] & 0x7 :
(parameters[2] & 0x70) >> 4;
parms = (ms_number == 6) ? parameters[0] : parameters[1]; parms = (ms_number == 6) ? parameters[0] : parameters[1];
printf("\tp1_int = %u\n", parms); printf("\tp1_int = %u\n", parms);
if(parms) if (parms) {
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", (800.0f / parms) / div_lut[r_div] ); printf("\tOutput (800Mhz PLL): %#.10f Mhz\n",
(800.0f / parms) / div_lut[r_div]);
}
} }
printf("\toutput divider = %u\n", div_lut[r_div]); printf("\toutput divider = %u\n", div_lut[r_div]);
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }
int si5351c_read_configuration(hackrf_device* device) { int si5351c_read_configuration(hackrf_device* device)
{
uint_fast8_t ms_number; uint_fast8_t ms_number;
int result; int result;
@ -224,7 +242,8 @@ int si5351c_read_configuration(hackrf_device* device) {
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }
static void usage() { static void usage()
{
printf("hackrf_clock - HackRF clock configuration utility\n"); printf("hackrf_clock - HackRF clock configuration utility\n");
printf("Usage:\n"); printf("Usage:\n");
printf("\t-h, --help: this help\n"); printf("\t-h, --help: this help\n");
@ -245,7 +264,8 @@ static struct option long_options[] = {
{0, 0, 0, 0}, {0, 0, 0, 0},
}; };
int main(int argc, char** argv) { int main(int argc, char** argv)
{
hackrf_device* device = NULL; hackrf_device* device = NULL;
int opt, option_index = 0; int opt, option_index = 0;
bool read = false; bool read = false;
@ -256,11 +276,14 @@ int main(int argc, char** argv) {
int result = hackrf_init(); int result = hackrf_init();
if (result) { if (result) {
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
while( (opt = getopt_long(argc, argv, "r:ao:d:h?", long_options, &option_index)) != EOF ) { while ((opt = getopt_long(argc, argv, "r:ao:d:h?", long_options, &option_index)) !=
EOF) {
switch (opt) { switch (opt) {
case 'r': case 'r':
read = true; read = true;
@ -291,36 +314,43 @@ int main(int argc, char** argv) {
} }
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
printf("argument error: %s (%d)\n", hackrf_error_name(result), result); printf("argument error: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (!clkout && !read) { if (!clkout && !read) {
fprintf(stderr, "Either read or enable CLKOUT option must be specified.\n"); fprintf(stderr,
"Either read or enable CLKOUT option must be specified.\n");
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
if (result) { if (result) {
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (clkout) { if (clkout) {
result = hackrf_set_clkout_enable(device, clkout_enable); result = hackrf_set_clkout_enable(device, clkout_enable);
if (result) { if (result) {
printf("hackrf_set_clkout_enable() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_set_clkout_enable() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (read) { if (read) {
if(clock == CLOCK_UNDEFINED) if (clock == CLOCK_UNDEFINED) {
si5351c_read_configuration(device); si5351c_read_configuration(device);
else { } else {
printf("%d\n", clock); printf("%d\n", clock);
si5351c_read_multisynth_config(device, clock); si5351c_read_multisynth_config(device, clock);
} }
@ -328,7 +358,9 @@ int main(int argc, char** argv) {
result = hackrf_close(device); result = hackrf_close(device);
if (result) { if (result) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -100,8 +100,8 @@ int main(int argc, char** argv)
ssize_t bytes_read; ssize_t bytes_read;
uint8_t* pdata = &data[0]; uint8_t* pdata = &data[0];
while ((opt = getopt_long(argc, argv, "x:d:h?", long_options, while ((opt = getopt_long(argc, argv, "x:d:h?", long_options, &option_index)) !=
&option_index)) != EOF) { EOF) {
switch (opt) { switch (opt) {
case 'x': case 'x':
path = optarg; path = optarg;
@ -129,13 +129,13 @@ int main(int argc, char** argv)
} }
infile = fopen(path, "rb"); infile = fopen(path, "rb");
if (infile == NULL) if (infile == NULL) {
{
fprintf(stderr, "Failed to open file: %s\n", path); fprintf(stderr, "Failed to open file: %s\n", path);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Get size of the file */ /* Get size of the file */
fseek(infile, 0, SEEK_END); /* Not really portable but work on major OS Linux/Win32 */ /* Not really portable but work on major OS Linux/Win32 */
fseek(infile, 0, SEEK_END);
length = ftell(infile); length = ftell(infile);
/* Move to start */ /* Move to start */
rewind(infile); rewind(infile);
@ -149,10 +149,11 @@ int main(int argc, char** argv)
total_length = length; total_length = length;
bytes_read = fread(data, 1, total_length, infile); bytes_read = fread(data, 1, total_length, infile);
if (bytes_read != total_length) if (bytes_read != total_length) {
{ fprintf(stderr,
fprintf(stderr, "Failed to read all bytes (read %d bytes instead of %d bytes).\n", "Failed to read all bytes (read %d bytes instead of %d bytes).\n",
(int)bytes_read, total_length); (int) bytes_read,
total_length);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -160,25 +161,30 @@ int main(int argc, char** argv)
result = hackrf_init(); result = hackrf_init();
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("LED1/2/3 blinking means CPLD program success.\nLED3/RED steady means error.\n"); printf("LED1/2/3 blinking means CPLD program success.\nLED3/RED steady means error.\n");
printf("Wait message 'Write finished' or in case of LED3/RED steady, Power OFF/Disconnect the HackRF.\n"); printf("Wait message 'Write finished' or in case of LED3/RED steady, Power OFF/Disconnect the HackRF.\n");
result = hackrf_cpld_write(device, pdata, total_length); result = hackrf_cpld_write(device, pdata, total_length);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
{ fprintf(stderr,
fprintf(stderr, "hackrf_cpld_write() failed: %s (%d)\n", "hackrf_cpld_write() failed: %s (%d)\n",
hackrf_error_name(result), result); hackrf_error_name(result),
result);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -189,10 +195,11 @@ int main(int argc, char** argv)
fflush(stdout); fflush(stdout);
result = hackrf_close(device); result = hackrf_close(device);
if( result != HACKRF_SUCCESS ) if (result != HACKRF_SUCCESS) {
{ fprintf(stderr,
fprintf(stderr, "hackrf_close() failed: %s (%d)\n", "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result), result); hackrf_error_name(result),
result);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;

View File

@ -36,7 +36,8 @@ typedef int bool;
#define REGISTER_INVALID 32767 #define REGISTER_INVALID 32767
int parse_int(char* s, uint32_t* const value) { int parse_int(char* s, uint32_t* const value)
{
uint_fast8_t base = 10; uint_fast8_t base = 10;
char* s_end; char* s_end;
long long_value; long long_value;
@ -63,19 +64,24 @@ int parse_int(char* s, uint32_t* const value) {
} }
} }
int max2837_read_register(hackrf_device* device, const uint16_t register_number) { int max2837_read_register(hackrf_device* device, const uint16_t register_number)
{
uint16_t register_value; uint16_t register_value;
int result = hackrf_max2837_read(device, (uint8_t)register_number, &register_value); int result =
hackrf_max2837_read(device, (uint8_t) register_number, &register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("[%2d] -> 0x%03x\n", register_number, register_value); printf("[%2d] -> 0x%03x\n", register_number, register_value);
} else { } else {
printf("hackrf_max2837_read() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_max2837_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
} }
int max2837_read_registers(hackrf_device* device) { int max2837_read_registers(hackrf_device* device)
{
uint16_t register_number; uint16_t register_number;
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
@ -91,33 +97,39 @@ int max2837_read_registers(hackrf_device* device) {
int max2837_write_register( int max2837_write_register(
hackrf_device* device, hackrf_device* device,
const uint16_t register_number, const uint16_t register_number,
const uint16_t register_value const uint16_t register_value)
) { {
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
result = hackrf_max2837_write(device, (uint8_t) register_number, register_value); result = hackrf_max2837_write(device, (uint8_t) register_number, register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("0x%03x -> [%2d]\n", register_value, register_number); printf("0x%03x -> [%2d]\n", register_value, register_number);
} else { } else {
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_max2837_write() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
} }
int si5351c_read_register(hackrf_device* device, const uint16_t register_number) { int si5351c_read_register(hackrf_device* device, const uint16_t register_number)
{
uint16_t register_value; uint16_t register_value;
int result = hackrf_si5351c_read(device, register_number, &register_value); int result = hackrf_si5351c_read(device, register_number, &register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("[%3d] -> 0x%02x\n", register_number, register_value); printf("[%3d] -> 0x%02x\n", register_number, register_value);
} else { } else {
printf("hackrf_si5351c_read() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_si5351c_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
} }
int si5351c_read_registers(hackrf_device* device) { int si5351c_read_registers(hackrf_device* device)
{
uint16_t register_number; uint16_t register_number;
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
@ -134,15 +146,17 @@ int si5351c_read_registers(hackrf_device* device) {
int si5351c_write_register( int si5351c_write_register(
hackrf_device* device, hackrf_device* device,
const uint16_t register_number, const uint16_t register_number,
const uint16_t register_value const uint16_t register_value)
) { {
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
result = hackrf_si5351c_write(device, register_number, register_value); result = hackrf_si5351c_write(device, register_number, register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("0x%2x -> [%3d]\n", register_value, register_number); printf("0x%2x -> [%3d]\n", register_value, register_number);
} else { } else {
printf("hackrf_max2837_write() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_max2837_write() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
@ -157,23 +171,28 @@ int si5351c_write_register(
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2 #define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3 #define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
void print_clk_control(uint16_t clk_ctrl) { void print_clk_control(uint16_t clk_ctrl)
{
uint8_t clk_src, clk_pwr; uint8_t clk_src, clk_pwr;
printf("\tclock control = \n"); printf("\tclock control = \n");
if(clk_ctrl & SI5351C_CLK_POWERDOWN) if (clk_ctrl & SI5351C_CLK_POWERDOWN) {
printf("\t\tPower Down\n"); printf("\t\tPower Down\n");
else } else {
printf("\t\tPower Up\n"); printf("\t\tPower Up\n");
if(clk_ctrl & SI5351C_CLK_INT_MODE) }
if (clk_ctrl & SI5351C_CLK_INT_MODE) {
printf("\t\tInt Mode\n"); printf("\t\tInt Mode\n");
else } else {
printf("\t\tFrac Mode\n"); printf("\t\tFrac Mode\n");
if(clk_ctrl & SI5351C_CLK_PLL_SRC) }
if (clk_ctrl & SI5351C_CLK_PLL_SRC) {
printf("\t\tPLL src B\n"); printf("\t\tPLL src B\n");
else } else {
printf("\t\tPLL src A\n"); printf("\t\tPLL src A\n");
if(clk_ctrl & SI5351C_CLK_INV) }
if (clk_ctrl & SI5351C_CLK_INV) {
printf("\t\tInverted\n"); printf("\t\tInverted\n");
}
clk_src = (clk_ctrl >> 2) & 0x3; clk_src = (clk_ctrl >> 2) & 0x3;
switch (clk_src) { switch (clk_src) {
case 0: case 0:
@ -206,7 +225,8 @@ void print_clk_control(uint16_t clk_ctrl) {
} }
} }
int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number) { int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_number)
{
uint_fast8_t i, reg_base, reg_number; uint_fast8_t i, reg_base, reg_number;
uint16_t parameters[8], clk_control; uint16_t parameters[8], clk_control;
uint32_t p1, p2, p3, r_div; uint32_t p1, p2, p3, r_div;
@ -229,22 +249,23 @@ int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_
} }
} }
p1 = ((parameters[2] & 0x03) << 16) p1 = ((parameters[2] & 0x03) << 16) | (parameters[3] << 8) |
| (parameters[3] << 8) parameters[4];
| parameters[4]; p2 = ((parameters[5] & 0x0F) << 16) | (parameters[6] << 8) |
p2 = ((parameters[5] & 0x0F) << 16) parameters[7];
| (parameters[6] << 8) p3 = ((parameters[5] & 0xF0) << 12) | (parameters[0] << 8) |
| parameters[7]; parameters[1];
p3 = ((parameters[5] & 0xF0) << 12)
| (parameters[0] << 8)
| parameters[1];
r_div = (parameters[2] >> 4) & 0x7; r_div = (parameters[2] >> 4) & 0x7;
printf("\tp1 = %u\n", p1); printf("\tp1 = %u\n", p1);
printf("\tp2 = %u\n", p2); printf("\tp2 = %u\n", p2);
printf("\tp3 = %u\n", p3); printf("\tp3 = %u\n", p3);
if(p3) if (p3) {
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", ((double)800 / (double)(((double)p1*p3 + p2 + 512*p3)/(double)(128*p3))) / div_lut[r_div] ); printf("\tOutput (800Mhz PLL): %#.10f Mhz\n",
((double) 800 /
(double) (((double) p1 * p3 + p2 + 512 * p3) / (double) (128 * p3))) /
div_lut[r_div]);
}
} else { } else {
// MS6 and 7 are integer only // MS6 and 7 are integer only
unsigned int parms; unsigned int parms;
@ -252,22 +273,27 @@ int si5351c_read_multisynth_config(hackrf_device* device, const uint_fast8_t ms_
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
uint_fast8_t reg_number = reg_base + i; uint_fast8_t reg_number = reg_base + i;
int result = hackrf_si5351c_read(device, reg_number, &parameters[i]); int result =
hackrf_si5351c_read(device, reg_number, &parameters[i]);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
return result; return result;
} }
} }
r_div = (ms_number == 6) ? parameters[2] & 0x7 : (parameters[2] & 0x70) >> 4 ; r_div = (ms_number == 6) ? parameters[2] & 0x7 :
(parameters[2] & 0x70) >> 4;
parms = (ms_number == 6) ? parameters[0] : parameters[1]; parms = (ms_number == 6) ? parameters[0] : parameters[1];
printf("\tp1_int = %u\n", parms); printf("\tp1_int = %u\n", parms);
if(parms) if (parms) {
printf("\tOutput (800Mhz PLL): %#.10f Mhz\n", (800.0f / parms) / div_lut[r_div] ); printf("\tOutput (800Mhz PLL): %#.10f Mhz\n",
(800.0f / parms) / div_lut[r_div]);
}
} }
printf("\toutput divider = %u\n", div_lut[r_div]); printf("\toutput divider = %u\n", div_lut[r_div]);
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }
int si5351c_read_configuration(hackrf_device* device) { int si5351c_read_configuration(hackrf_device* device)
{
uint_fast8_t ms_number; uint_fast8_t ms_number;
int result; int result;
@ -287,20 +313,25 @@ int si5351c_read_configuration(hackrf_device* device) {
* we use that name here and present it to the user. * we use that name here and present it to the user.
*/ */
int rffc5072_read_register(hackrf_device* device, const uint16_t register_number) { int rffc5072_read_register(hackrf_device* device, const uint16_t register_number)
{
uint16_t register_value; uint16_t register_value;
int result = hackrf_rffc5071_read(device, (uint8_t)register_number, &register_value); int result =
hackrf_rffc5071_read(device, (uint8_t) register_number, &register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("[%2d] -> 0x%03x\n", register_number, register_value); printf("[%2d] -> 0x%03x\n", register_number, register_value);
} else { } else {
printf("hackrf_rffc5071_read() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_rffc5071_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
} }
int rffc5072_read_registers(hackrf_device* device) { int rffc5072_read_registers(hackrf_device* device)
{
uint16_t register_number; uint16_t register_number;
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
@ -317,15 +348,17 @@ int rffc5072_read_registers(hackrf_device* device) {
int rffc5072_write_register( int rffc5072_write_register(
hackrf_device* device, hackrf_device* device,
const uint16_t register_number, const uint16_t register_number,
const uint16_t register_value const uint16_t register_value)
) { {
int result = HACKRF_SUCCESS; int result = HACKRF_SUCCESS;
result = hackrf_rffc5071_write(device, (uint8_t) register_number, register_value); result = hackrf_rffc5071_write(device, (uint8_t) register_number, register_value);
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
printf("0x%03x -> [%2d]\n", register_value, register_number); printf("0x%03x -> [%2d]\n", register_value, register_number);
} else { } else {
printf("hackrf_rffc5071_write() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_rffc5071_write() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return result; return result;
@ -338,8 +371,8 @@ enum parts {
PART_RFFC5072 = 3, PART_RFFC5072 = 3,
}; };
int read_register(hackrf_device* device, uint8_t part, int read_register(hackrf_device* device, uint8_t part, const uint16_t register_number)
const uint16_t register_number) { {
switch (part) { switch (part) {
case PART_MAX2837: case PART_MAX2837:
return max2837_read_register(device, register_number); return max2837_read_register(device, register_number);
@ -351,7 +384,8 @@ int read_register(hackrf_device* device, uint8_t part,
return HACKRF_ERROR_INVALID_PARAM; return HACKRF_ERROR_INVALID_PARAM;
} }
int read_registers(hackrf_device* device, uint8_t part) { int read_registers(hackrf_device* device, uint8_t part)
{
switch (part) { switch (part) {
case PART_MAX2837: case PART_MAX2837:
return max2837_read_registers(device); return max2837_read_registers(device);
@ -363,9 +397,12 @@ int read_registers(hackrf_device* device, uint8_t part) {
return HACKRF_ERROR_INVALID_PARAM; return HACKRF_ERROR_INVALID_PARAM;
} }
int write_register(hackrf_device* device, uint8_t part, int write_register(
hackrf_device* device,
uint8_t part,
const uint16_t register_number, const uint16_t register_number,
const uint16_t register_value) { const uint16_t register_value)
{
switch (part) { switch (part) {
case PART_MAX2837: case PART_MAX2837:
return max2837_write_register(device, register_number, register_value); return max2837_write_register(device, register_number, register_value);
@ -377,30 +414,38 @@ int write_register(hackrf_device* device, uint8_t part,
return HACKRF_ERROR_INVALID_PARAM; return HACKRF_ERROR_INVALID_PARAM;
} }
static const char * mode_name(uint32_t mode) { static const char* mode_name(uint32_t mode)
{
const char* mode_names[] = {"IDLE", "WAIT", "RX", "TX_START", "TX_RUN"}; const char* mode_names[] = {"IDLE", "WAIT", "RX", "TX_START", "TX_RUN"};
const uint32_t num_modes = sizeof(mode_names) / sizeof(mode_names[0]); const uint32_t num_modes = sizeof(mode_names) / sizeof(mode_names[0]);
if (mode < num_modes) if (mode < num_modes) {
return mode_names[mode]; return mode_names[mode];
else } else {
return "UNKNOWN"; return "UNKNOWN";
} }
}
static const char * error_name(uint32_t error) { static const char* error_name(uint32_t error)
{
const char* error_names[] = {"NONE", "RX_TIMEOUT", "TX_TIMEOUT"}; const char* error_names[] = {"NONE", "RX_TIMEOUT", "TX_TIMEOUT"};
const uint32_t num_errors = sizeof(error_names) / sizeof(error_names[0]); const uint32_t num_errors = sizeof(error_names) / sizeof(error_names[0]);
if (error < num_errors) if (error < num_errors) {
return error_names[error]; return error_names[error];
else } else {
return "UNKNOWN"; return "UNKNOWN";
} }
}
static void print_state(hackrf_m0_state *state) { static void print_state(hackrf_m0_state* state)
{
printf("M0 state:\n"); printf("M0 state:\n");
printf("Requested mode: %u (%s) [%s]\n", printf("Requested mode: %u (%s) [%s]\n",
state->requested_mode, mode_name(state->requested_mode), state->requested_mode,
mode_name(state->requested_mode),
state->request_flag ? "pending" : "complete"); state->request_flag ? "pending" : "complete");
printf("Active mode: %u (%s)\n", state->active_mode, mode_name(state->active_mode)); printf("Active mode: %u (%s)\n",
state->active_mode,
mode_name(state->active_mode));
printf("M0 count: %u bytes\n", state->m0_count); printf("M0 count: %u bytes\n", state->m0_count);
printf("M4 count: %u bytes\n", state->m4_count); printf("M4 count: %u bytes\n", state->m4_count);
printf("Number of shortfalls: %u\n", state->num_shortfalls); printf("Number of shortfalls: %u\n", state->num_shortfalls);
@ -411,7 +456,8 @@ static void print_state(hackrf_m0_state *state) {
printf("Error: %u (%s)\n", state->error, error_name(state->error)); printf("Error: %u (%s)\n", state->error, error_name(state->error));
} }
static void usage() { static void usage()
{
printf("\nUsage:\n"); printf("\nUsage:\n");
printf("\t-h, --help: this help\n"); printf("\t-h, --help: this help\n");
printf("\t-n, --register <n>: set register number for read/write operations\n"); printf("\t-n, --register <n>: set register number for read/write operations\n");
@ -451,7 +497,8 @@ static struct option long_options[] = {
{0, 0, 0, 0}, {0, 0, 0, 0},
}; };
int main(int argc, char** argv) { int main(int argc, char** argv)
{
int opt; int opt;
uint32_t register_number = REGISTER_INVALID; uint32_t register_number = REGISTER_INVALID;
uint32_t register_value; uint32_t register_value;
@ -472,11 +519,18 @@ int main(int argc, char** argv) {
int result = hackrf_init(); int result = hackrf_init();
if (result) { if (result) {
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
while( (opt = getopt_long(argc, argv, "n:rw:d:cmsfST:R:h?u:", long_options, &option_index)) != EOF ) { while ((opt = getopt_long(
argc,
argv,
"n:rw:d:cmsfST:R:h?u:",
long_options,
&option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'n': case 'n':
result = parse_int(optarg, &register_number); result = parse_int(optarg, &register_number);
@ -552,7 +606,9 @@ int main(int argc, char** argv) {
} }
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
printf("argument error: %s (%d)\n", hackrf_error_name(result), result); printf("argument error: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -576,13 +632,15 @@ int main(int argc, char** argv) {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(!(write || read || dump_config || dump_state || set_tx_limit || set_rx_limit || set_ui)) { if (!(write || read || dump_config || dump_state || set_tx_limit ||
set_rx_limit || set_ui)) {
fprintf(stderr, "Specify read, write, or config option.\n"); fprintf(stderr, "Specify read, write, or config option.\n");
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if(part == PART_NONE && !set_ui && !dump_state && !set_tx_limit && !set_rx_limit) { if (part == PART_NONE && !set_ui && !dump_state && !set_tx_limit &&
!set_rx_limit) {
fprintf(stderr, "Specify a part to read, write, or print config from.\n"); fprintf(stderr, "Specify a part to read, write, or print config from.\n");
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
@ -590,7 +648,9 @@ int main(int argc, char** argv) {
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
if (result) { if (result) {
printf("hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -613,7 +673,9 @@ int main(int argc, char** argv) {
if (set_tx_limit) { if (set_tx_limit) {
result = hackrf_set_tx_underrun_limit(device, tx_limit); result = hackrf_set_tx_underrun_limit(device, tx_limit);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
printf("hackrf_set_tx_underrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_set_tx_underrun_limit() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -621,7 +683,9 @@ int main(int argc, char** argv) {
if (set_rx_limit) { if (set_rx_limit) {
result = hackrf_set_rx_overrun_limit(device, rx_limit); result = hackrf_set_rx_overrun_limit(device, rx_limit);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
printf("hackrf_set_rx_overrun_limit() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_set_rx_overrun_limit() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -630,7 +694,9 @@ int main(int argc, char** argv) {
hackrf_m0_state state; hackrf_m0_state state;
result = hackrf_get_m0_state(device, &state); result = hackrf_get_m0_state(device, &state);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
printf("hackrf_get_m0_state() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_get_m0_state() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
print_state(&state); print_state(&state);
@ -642,7 +708,9 @@ int main(int argc, char** argv) {
result = hackrf_close(device); result = hackrf_close(device);
if (result) { if (result) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -40,13 +40,16 @@ int main(void)
result = hackrf_init(); result = hackrf_init();
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("hackrf_info version: %s\n", TOOL_RELEASE); printf("hackrf_info version: %s\n", TOOL_RELEASE);
printf("libhackrf version: %s (%s)\n", hackrf_library_release(), printf("libhackrf version: %s (%s)\n",
hackrf_library_release(),
hackrf_library_version()); hackrf_library_version());
list = hackrf_device_list(); list = hackrf_device_list();
@ -57,20 +60,24 @@ int main(void)
} }
for (i = 0; i < list->devicecount; i++) { for (i = 0; i < list->devicecount; i++) {
if (i > 0) if (i > 0) {
printf("\n"); printf("\n");
}
printf("Found HackRF\n"); printf("Found HackRF\n");
printf("Index: %d\n", i); printf("Index: %d\n", i);
if (list->serial_numbers[i]) if (list->serial_numbers[i]) {
printf("Serial number: %s\n", list->serial_numbers[i]); printf("Serial number: %s\n", list->serial_numbers[i]);
}
device = NULL; device = NULL;
result = hackrf_device_list_open(list, i, &device); result = hackrf_device_list_open(list, i, &device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
if (result == HACKRF_ERROR_LIBUSB) { if (result == HACKRF_ERROR_LIBUSB) {
continue; continue;
} }
@ -79,33 +86,44 @@ int main(void)
result = hackrf_board_id_read(device, &board_id); result = hackrf_board_id_read(device, &board_id);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_board_id_read() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_board_id_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Board ID Number: %d (%s)\n", board_id, printf("Board ID Number: %d (%s)\n",
board_id,
hackrf_board_id_name(board_id)); hackrf_board_id_name(board_id));
result = hackrf_version_string_read(device, &version[0], 255); result = hackrf_version_string_read(device, &version[0], 255);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_version_string_read() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_version_string_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_usb_api_version_read(device, &usb_version); result = hackrf_usb_api_version_read(device, &usb_version);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_usb_api_version_read() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_usb_api_version_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Firmware Version: %s (API:%x.%02x)\n", version, printf("Firmware Version: %s (API:%x.%02x)\n",
(usb_version>>8)&0xFF, usb_version&0xFF); version,
(usb_version >> 8) & 0xFF,
usb_version & 0xFF);
result = hackrf_board_partid_serialno_read(device, &read_partid_serialno); result = hackrf_board_partid_serialno_read(device, &read_partid_serialno);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_board_partid_serialno_read() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_board_partid_serialno_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Part ID Number: 0x%08x 0x%08x\n", printf("Part ID Number: 0x%08x 0x%08x\n",
@ -113,15 +131,19 @@ int main(void)
read_partid_serialno.part_id[1]); read_partid_serialno.part_id[1]);
result = hackrf_get_operacake_boards(device, &operacakes[0]); result = hackrf_get_operacake_boards(device, &operacakes[0]);
if ((result != HACKRF_SUCCESS) && (result != HACKRF_ERROR_USB_API_VERSION)) { if ((result != HACKRF_SUCCESS) &&
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n", (result != HACKRF_ERROR_USB_API_VERSION)) {
hackrf_error_name(result), result); fprintf(stderr,
"hackrf_get_operacake_boards() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
for (j = 0; j < 8; j++) { for (j = 0; j < 8; j++) {
if(operacakes[j] == HACKRF_OPERACAKE_ADDRESS_INVALID) if (operacakes[j] == HACKRF_OPERACAKE_ADDRESS_INVALID) {
break; break;
}
printf("Opera Cake found, address: %d\n", operacakes[j]); printf("Opera Cake found, address: %d\n", operacakes[j]);
} }
} }
@ -129,9 +151,12 @@ int main(void)
#ifdef HACKRF_ISSUE_609_IS_FIXED #ifdef HACKRF_ISSUE_609_IS_FIXED
uint32_t cpld_crc = 0; uint32_t cpld_crc = 0;
result = hackrf_cpld_checksum(device, &cpld_crc); result = hackrf_cpld_checksum(device, &cpld_crc);
if ((result != HACKRF_SUCCESS) && (result != HACKRF_ERROR_USB_API_VERSION)) { if ((result != HACKRF_SUCCESS) &&
fprintf(stderr, "hackrf_cpld_checksum() failed: %s (%d)\n", (result != HACKRF_ERROR_USB_API_VERSION)) {
hackrf_error_name(result), result); fprintf(stderr,
"hackrf_cpld_checksum() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (result == HACKRF_SUCCESS) { if (result == HACKRF_SUCCESS) {
@ -141,8 +166,10 @@ int main(void)
result = hackrf_close(device); result = hackrf_close(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
} }

View File

@ -41,7 +41,8 @@ typedef int bool;
#define GPIO_TEST_DISABLED 0xFFFF #define GPIO_TEST_DISABLED 0xFFFF
static void usage() { static void usage()
{
printf("\nUsage:\n"); printf("\nUsage:\n");
printf("\t-h, --help: this help\n"); printf("\t-h, --help: this help\n");
printf("\t-d, --device <n>: specify a particular device by serial number\n"); printf("\t-d, --device <n>: specify a particular device by serial number\n");
@ -66,7 +67,8 @@ static struct option long_options[] = {
{0, 0, 0, 0}, {0, 0, 0, 0},
}; };
int parse_uint16(char* const s, uint16_t* const value) { int parse_uint16(char* const s, uint16_t* const value)
{
char* s_end = s; char* s_end = s;
const long long_value = strtol(s, &s_end, 10); const long long_value = strtol(s, &s_end, 10);
if ((s != s_end) && (*s_end == 0)) { if ((s != s_end) && (*s_end == 0)) {
@ -77,7 +79,8 @@ int parse_uint16(char* const s, uint16_t* const value) {
} }
} }
int parse_uint32(char* const s, uint32_t* const value) { int parse_uint32(char* const s, uint32_t* const value)
{
char* s_end = s; char* s_end = s;
const long long_value = strtol(s, &s_end, 10); const long long_value = strtol(s, &s_end, 10);
if ((s != s_end) && (*s_end == 0)) { if ((s != s_end) && (*s_end == 0)) {
@ -88,15 +91,17 @@ int parse_uint32(char* const s, uint32_t* const value) {
} }
} }
int parse_port(char* str, uint8_t* port) { int parse_port(char* str, uint8_t* port)
{
uint16_t tmp_port; uint16_t tmp_port;
int result; int result;
if (str[0] == 'A' || str[0] == 'B') { if (str[0] == 'A' || str[0] == 'B') {
// The port was specified as a side and number eg. A1 or B3 // The port was specified as a side and number eg. A1 or B3
result = parse_uint16(str + 1, &tmp_port); result = parse_uint16(str + 1, &tmp_port);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
}
if (tmp_port >= 5 || tmp_port <= 0) { if (tmp_port >= 5 || tmp_port <= 0) {
fprintf(stderr, "invalid port: %s\n", str); fprintf(stderr, "invalid port: %s\n", str);
@ -114,15 +119,17 @@ int parse_port(char* str, uint8_t* port) {
} }
} else { } else {
result = parse_uint16(str, &tmp_port); result = parse_uint16(str, &tmp_port);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
} }
}
*port = tmp_port & 0xFF; *port = tmp_port & 0xFF;
// printf("Port: %d\n", *port); // printf("Port: %d\n", *port);
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }
int parse_range(char* s, hackrf_operacake_freq_range* range) { int parse_range(char* s, hackrf_operacake_freq_range* range)
{
char port[16]; char port[16];
float min; float min;
float max; float max;
@ -131,8 +138,9 @@ int parse_range(char* s, hackrf_operacake_freq_range* range) {
// Read frequency as a float here to support scientific notation (e.g: 1e6) // Read frequency as a float here to support scientific notation (e.g: 1e6)
if (sscanf(s, "%15[^:]:%f:%f", port, &min, &max) == 3) { if (sscanf(s, "%15[^:]:%f:%f", port, &min, &max) == 3) {
result = parse_port(port, &(range->port)); result = parse_port(port, &(range->port));
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
}
range->freq_min = min; range->freq_min = min;
range->freq_max = max; range->freq_max = max;
@ -141,7 +149,8 @@ int parse_range(char* s, hackrf_operacake_freq_range* range) {
return HACKRF_ERROR_INVALID_PARAM; return HACKRF_ERROR_INVALID_PARAM;
} }
int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) { int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time)
{
int result; int result;
char port[16]; char port[16];
float dwell; float dwell;
@ -149,8 +158,9 @@ int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
// Read dwell as a float here to support scientific notation (e.g: 1e6) // Read dwell as a float here to support scientific notation (e.g: 1e6)
if (sscanf(s, "%15[^:]:%f", port, &dwell) == 2) { if (sscanf(s, "%15[^:]:%f", port, &dwell) == 2) {
result = parse_port(port, &dwell_time->port); result = parse_port(port, &dwell_time->port);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
}
if (dwell == 0) { if (dwell == 0) {
fprintf(stderr, "dwell time cannot be 0\n"); fprintf(stderr, "dwell time cannot be 0\n");
@ -160,8 +170,9 @@ int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} else if (sscanf(s, "%15[^:]", port) == 1) { } else if (sscanf(s, "%15[^:]", port) == 1) {
result = parse_port(port, &dwell_time->port); result = parse_port(port, &dwell_time->port);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
}
// This will be replaced with the default dwell time later. // This will be replaced with the default dwell time later.
dwell_time->dwell = 0; dwell_time->dwell = 0;
@ -170,7 +181,8 @@ int parse_dwell(char* s, hackrf_operacake_dwell_time* dwell_time) {
return HACKRF_ERROR_INVALID_PARAM; return HACKRF_ERROR_INVALID_PARAM;
} }
int main(int argc, char** argv) { int main(int argc, char** argv)
{
int opt; int opt;
const char* serial_number = NULL; const char* serial_number = NULL;
uint8_t operacake_address = 0; uint8_t operacake_address = 0;
@ -194,11 +206,18 @@ int main(int argc, char** argv) {
int result = hackrf_init(); int result = hackrf_init();
if (result) { if (result) {
printf("hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return -1; return -1;
} }
while( (opt = getopt_long(argc, argv, "d:o:a:m:b:lf:t:w:hg?", long_options, &option_index)) != EOF ) { while ((opt = getopt_long(
argc,
argv,
"d:o:a:m:b:lf:t:w:hg?",
long_options,
&option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'd': case 'd':
serial_number = optarg; serial_number = optarg;
@ -325,16 +344,20 @@ int main(int argc, char** argv) {
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (set_mode) { if (set_mode) {
result = hackrf_set_operacake_mode(device, operacake_address, mode); result = hackrf_set_operacake_mode(device, operacake_address, mode);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_set_operacake_mode() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_set_operacake_mode() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -342,8 +365,10 @@ int main(int argc, char** argv) {
if (list) { if (list) {
result = hackrf_get_operacake_boards(device, operacakes); result = hackrf_get_operacake_boards(device, operacakes);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_get_operacake_boards() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_get_operacake_boards() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("Opera Cakes found: "); printf("Opera Cakes found: ");
@ -365,18 +390,24 @@ int main(int argc, char** argv) {
operacake_count++; operacake_count++;
} }
} }
if(!operacake_count) if (!operacake_count) {
printf("None"); printf("None");
}
printf("\n"); printf("\n");
} }
if (gpio_test) { if (gpio_test) {
uint16_t test_result; uint16_t test_result;
uint8_t reg, mask = 0x7; uint8_t reg, mask = 0x7;
result = hackrf_operacake_gpio_test(device, operacake_address, &test_result); result = hackrf_operacake_gpio_test(
device,
operacake_address,
&test_result);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_operacake_gpio_test() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_operacake_gpio_test() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -387,31 +418,36 @@ int main(int argc, char** argv) {
fprintf(stderr, "GPIO test failed\n"); fprintf(stderr, "GPIO test failed\n");
fprintf(stderr, "Pin\tHigh\tShorts\tLow\n"); fprintf(stderr, "Pin\tHigh\tShorts\tLow\n");
reg = test_result & mask; reg = test_result & mask;
fprintf(stderr, "u2ctrl1\t%d\t%d\t%d\n", fprintf(stderr,
"u2ctrl1\t%d\t%d\t%d\n",
(reg >> 2) & 1, (reg >> 2) & 1,
(reg >> 1) & 1, (reg >> 1) & 1,
reg & 1); reg & 1);
test_result >>= 3; test_result >>= 3;
reg = test_result & mask; reg = test_result & mask;
fprintf(stderr, "u2ctrl0\t%d\t%d\t%d\n", fprintf(stderr,
"u2ctrl0\t%d\t%d\t%d\n",
(reg >> 2) & 1, (reg >> 2) & 1,
(reg >> 1) & 1, (reg >> 1) & 1,
reg & 1); reg & 1);
test_result >>= 3; test_result >>= 3;
reg = test_result & mask; reg = test_result & mask;
fprintf(stderr, "u3ctrl1\t%d\t%d\t%d\n", fprintf(stderr,
"u3ctrl1\t%d\t%d\t%d\n",
(reg >> 2) & 1, (reg >> 2) & 1,
(reg >> 1) & 1, (reg >> 1) & 1,
reg & 1); reg & 1);
test_result >>= 3; test_result >>= 3;
reg = test_result & mask; reg = test_result & mask;
fprintf(stderr, "u3ctrl0\t%d\t%d\t%d\n", fprintf(stderr,
"u3ctrl0\t%d\t%d\t%d\n",
(reg >> 2) & 1, (reg >> 2) & 1,
(reg >> 1) & 1, (reg >> 1) & 1,
reg & 1); reg & 1);
test_result >>= 3; test_result >>= 3;
reg = test_result & mask; reg = test_result & mask;
fprintf(stderr, "u1ctrl \t%d\t%d\t%d\n", fprintf(stderr,
"u1ctrl \t%d\t%d\t%d\n",
(reg >> 2) & 1, (reg >> 2) & 1,
(reg >> 1) & 1, (reg >> 1) & 1,
reg & 1); reg & 1);
@ -436,13 +472,21 @@ int main(int argc, char** argv) {
port_b = 4; port_b = 4;
} }
} }
if(((port_a<=3) && (port_b<=3)) || ((port_a>=4) && (port_b>=4))) { if (((port_a <= 3) && (port_b <= 3)) ||
fprintf(stderr, "Port A and B cannot be connected to the same side\n"); ((port_a >= 4) && (port_b >= 4))) {
fprintf(stderr,
"Port A and B cannot be connected to the same side\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_set_operacake_ports(device, operacake_address, port_a, port_b); result = hackrf_set_operacake_ports(
device,
operacake_address,
port_a,
port_b);
if (result) { if (result) {
printf("hackrf_set_operacake_ports() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_set_operacake_ports() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -450,7 +494,9 @@ int main(int argc, char** argv) {
if (range_idx) { if (range_idx) {
result = hackrf_set_operacake_freq_ranges(device, ranges, range_idx); result = hackrf_set_operacake_freq_ranges(device, ranges, range_idx);
if (result) { if (result) {
printf("hackrf_set_operacake_freq_ranges() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_set_operacake_freq_ranges() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return -1; return -1;
} }
} }
@ -459,7 +505,8 @@ int main(int argc, char** argv) {
for (i = 0; i < dwell_idx; i++) { for (i = 0; i < dwell_idx; i++) {
if (dwell_times[i].dwell == 0) { if (dwell_times[i].dwell == 0) {
if (default_dwell == 0) { if (default_dwell == 0) {
fprintf(stderr, "port '%u' set to use default dwell time, but default dwell time is not set. Use -w argument to set default dwell time.\n", fprintf(stderr,
"port '%u' set to use default dwell time, but default dwell time is not set. Use -w argument to set default dwell time.\n",
dwell_times[i].port); dwell_times[i].port);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -468,14 +515,18 @@ int main(int argc, char** argv) {
} }
result = hackrf_set_operacake_dwell_times(device, dwell_times, dwell_idx); result = hackrf_set_operacake_dwell_times(device, dwell_times, dwell_idx);
if (result) { if (result) {
printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_set_operacake_dwell_times() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return -1; return -1;
} }
} }
result = hackrf_close(device); result = hackrf_close(device);
if (result) { if (result) {
printf("hackrf_close() failed: %s (%d)\n", hackrf_error_name(result), result); printf("hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return -1; return -1;
} }
hackrf_exit(); hackrf_exit();

View File

@ -73,8 +73,7 @@ int compatibility_check(uint8_t* data, int length, hackrf_device* device)
uint8_t board_id; uint8_t board_id;
char* dev_str; char* dev_str;
hackrf_board_id_read(device, &board_id); hackrf_board_id_read(device, &board_id);
switch(board_id) switch (board_id) {
{
case BOARD_ID_JAWBREAKER: case BOARD_ID_JAWBREAKER:
dev_str = "HackRF Jawbreaker"; dev_str = "HackRF Jawbreaker";
str_len = 17; str_len = 17;
@ -102,10 +101,11 @@ int compatibility_check(uint8_t* data, int length, hackrf_device* device)
break; break;
} }
} }
if(match) if (match) {
return 0; return 0;
} }
} }
}
return 1; return 1;
} }
@ -178,7 +178,11 @@ int main(int argc, char** argv)
bool clear_status = false; bool clear_status = false;
uint16_t usb_api; uint16_t usb_api;
while ((opt = getopt_long(argc, argv, "a:l:r:w:id:scvRh?", long_options, while ((opt = getopt_long(
argc,
argv,
"a:l:r:w:id:scvRh?",
long_options,
&option_index)) != EOF) { &option_index)) != EOF) {
switch (opt) { switch (opt) {
case 'a': case 'a':
@ -235,8 +239,10 @@ int main(int argc, char** argv)
} }
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "argument error: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "argument error: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -254,16 +260,16 @@ int main(int argc, char** argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if( write ) if (write) {
{
infile = fopen(path, "rb"); infile = fopen(path, "rb");
if(infile == NULL) if (infile == NULL) {
{
printf("Error opening file %s\n", path); printf("Error opening file %s\n", path);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
/* Get size of the file */ /* Get size of the file */
fseek(infile, 0, SEEK_END); /* Not really portable but work on major OS Linux/Win32 */ fseek(infile,
0,
SEEK_END); /* Not really portable but work on major OS Linux/Win32 */
length = ftell(infile); length = ftell(infile);
/* Move to start */ /* Move to start */
rewind(infile); rewind(infile);
@ -272,25 +278,26 @@ int main(int argc, char** argv)
if (length == 0) { if (length == 0) {
fprintf(stderr, "Requested transfer of zero bytes.\n"); fprintf(stderr, "Requested transfer of zero bytes.\n");
if(infile != NULL) if (infile != NULL) {
fclose(infile); fclose(infile);
}
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if ((length > MAX_LENGTH) || (address > MAX_LENGTH) if ((length > MAX_LENGTH) || (address > MAX_LENGTH) ||
|| ((address + length) > MAX_LENGTH)) { ((address + length) > MAX_LENGTH)) {
fprintf(stderr, "Request exceeds size of flash memory.\n"); fprintf(stderr, "Request exceeds size of flash memory.\n");
if(infile != NULL) if (infile != NULL) {
fclose(infile); fclose(infile);
}
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (read) { if (read) {
infile = fopen(path, "wb"); infile = fopen(path, "wb");
if(infile == NULL) if (infile == NULL) {
{
printf("Error to open file %s\n", path); printf("Error to open file %s\n", path);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -298,23 +305,29 @@ int main(int argc, char** argv)
result = hackrf_init(); result = hackrf_init();
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (read_status) { if (read_status) {
result = hackrf_spiflash_status(device, status); result = hackrf_spiflash_status(device, status);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_status() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_spiflash_status() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (!verbose) { if (!verbose) {
@ -340,8 +353,10 @@ int main(int argc, char** argv)
if (clear_status) { if (clear_status) {
result = hackrf_spiflash_clear_status(device); result = hackrf_spiflash_clear_status(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_clear_status() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_spiflash_clear_status() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
@ -349,14 +364,19 @@ int main(int argc, char** argv)
if (read) { if (read) {
ssize_t bytes_written; ssize_t bytes_written;
tmp_length = length; tmp_length = length;
while (tmp_length) while (tmp_length) {
{
xfer_len = (tmp_length > 256) ? 256 : tmp_length; xfer_len = (tmp_length > 256) ? 256 : tmp_length;
if( verbose ) printf("Reading %d bytes from 0x%06x.\n", xfer_len, address); if (verbose) {
printf("Reading %d bytes from 0x%06x.\n",
xfer_len,
address);
}
result = hackrf_spiflash_read(device, address, xfer_len, pdata); result = hackrf_spiflash_read(device, address, xfer_len, pdata);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_read() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_spiflash_read() failed: %s (%d)\n",
hackrf_error_name(result),
result);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -367,7 +387,8 @@ int main(int argc, char** argv)
} }
bytes_written = fwrite(data, 1, length, infile); bytes_written = fwrite(data, 1, length, infile);
if (bytes_written != length) { if (bytes_written != length) {
fprintf(stderr, "Failed write to file (wrote %d bytes).\n", fprintf(stderr,
"Failed write to file (wrote %d bytes).\n",
(int) bytes_written); (int) bytes_written);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
@ -378,7 +399,8 @@ int main(int argc, char** argv)
if (write) { if (write) {
ssize_t bytes_read = fread(data, 1, length, infile); ssize_t bytes_read = fread(data, 1, length, infile);
if (bytes_read != length) { if (bytes_read != length) {
fprintf(stderr, "Failed read file (read %d bytes).\n", fprintf(stderr,
"Failed read file (read %d bytes).\n",
(int) bytes_read); (int) bytes_read);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
@ -397,20 +419,30 @@ int main(int argc, char** argv)
printf("Erasing SPI flash.\n"); printf("Erasing SPI flash.\n");
result = hackrf_spiflash_erase(device); result = hackrf_spiflash_erase(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_erase() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_spiflash_erase() failed: %s (%d)\n",
hackrf_error_name(result),
result);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if( !verbose ) printf("Writing %d bytes at 0x%06x.\n", length, address); if (!verbose) {
printf("Writing %d bytes at 0x%06x.\n", length, address);
}
while (length) { while (length) {
xfer_len = (length > 256) ? 256 : length; xfer_len = (length > 256) ? 256 : length;
if( verbose ) printf("Writing %d bytes at 0x%06x.\n", xfer_len, address); if (verbose) {
printf("Writing %d bytes at 0x%06x.\n",
xfer_len,
address);
}
result = hackrf_spiflash_write(device, address, xfer_len, pdata); result = hackrf_spiflash_write(device, address, xfer_len, pdata);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_spiflash_write() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_spiflash_write() failed: %s (%d)\n",
hackrf_error_name(result),
result);
fclose(infile); fclose(infile);
infile = NULL; infile = NULL;
return EXIT_FAILURE; return EXIT_FAILURE;
@ -431,11 +463,15 @@ int main(int argc, char** argv)
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
if (result == HACKRF_ERROR_USB_API_VERSION) { if (result == HACKRF_ERROR_USB_API_VERSION) {
hackrf_usb_api_version_read(device, &usb_api); hackrf_usb_api_version_read(device, &usb_api);
fprintf(stderr, "Reset is not supported by firmware API %x.%02x\n", fprintf(stderr,
(usb_api>>8)&0xFF, usb_api&0xFF); "Reset is not supported by firmware API %x.%02x\n",
(usb_api >> 8) & 0xFF,
usb_api & 0xFF);
} else { } else {
fprintf(stderr, "hackrf_reset() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_reset() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} }
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -443,8 +479,10 @@ int main(int argc, char** argv)
result = hackrf_close(device); result = hackrf_close(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View File

@ -58,7 +58,8 @@ typedef int32_t ssize_t;
#define strtoull _strtoui64 #define strtoull _strtoui64
#define snprintf _snprintf #define snprintf _snprintf
int gettimeofday(struct timeval *tv, void* ignored) { int gettimeofday(struct timeval* tv, void* ignored)
{
FILETIME ft; FILETIME ft;
unsigned __int64 tmp = 0; unsigned __int64 tmp = 0;
if (NULL != tv) { if (NULL != tv) {
@ -112,11 +113,13 @@ int num_ranges = 0;
uint16_t frequencies[MAX_SWEEP_RANGES * 2]; uint16_t frequencies[MAX_SWEEP_RANGES * 2];
int step_count; int step_count;
static float TimevalDiff(const struct timeval *a, const struct timeval *b) { static float TimevalDiff(const struct timeval* a, const struct timeval* b)
{
return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec); return (a->tv_sec - b->tv_sec) + 1e-6f * (a->tv_usec - b->tv_usec);
} }
int parse_u32(char* s, uint32_t* const value) { int parse_u32(char* s, uint32_t* const value)
{
uint_fast8_t base = 10; uint_fast8_t base = 10;
char* s_end; char* s_end;
uint64_t ulong_value; uint64_t ulong_value;
@ -143,21 +146,25 @@ int parse_u32(char* s, uint32_t* const value) {
} }
} }
int parse_u32_range(char* s, uint32_t* const value_min, uint32_t* const value_max) { int parse_u32_range(char* s, uint32_t* const value_min, uint32_t* const value_max)
{
int result; int result;
char* sep = strchr(s, ':'); char* sep = strchr(s, ':');
if (!sep) if (!sep) {
return HACKRF_ERROR_INVALID_PARAM; return HACKRF_ERROR_INVALID_PARAM;
}
*sep = 0; *sep = 0;
result = parse_u32(s, value_min); result = parse_u32(s, value_min);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
}
result = parse_u32(sep + 1, value_max); result = parse_u32(sep + 1, value_max);
if (result != HACKRF_SUCCESS) if (result != HACKRF_SUCCESS) {
return result; return result;
}
return HACKRF_SUCCESS; return HACKRF_SUCCESS;
} }
@ -203,7 +210,8 @@ float logPower(fftwf_complex in, float scale)
return (float) (log2(magsq) * 10.0f / log2(10.0f)); return (float) (log2(magsq) * 10.0f / log2(10.0f));
} }
int rx_callback(hackrf_transfer* transfer) { int rx_callback(hackrf_transfer* transfer)
{
int8_t* buf; int8_t* buf;
uint8_t* ubuf; uint8_t* ubuf;
uint64_t frequency; /* in Hz */ uint64_t frequency; /* in Hz */
@ -228,9 +236,13 @@ int rx_callback(hackrf_transfer* transfer) {
for (j = 0; j < BLOCKS_PER_TRANSFER; j++) { for (j = 0; j < BLOCKS_PER_TRANSFER; j++) {
ubuf = (uint8_t*) buf; ubuf = (uint8_t*) buf;
if (ubuf[0] == 0x7F && ubuf[1] == 0x7F) { if (ubuf[0] == 0x7F && ubuf[1] == 0x7F) {
frequency = ((uint64_t)(ubuf[9]) << 56) | ((uint64_t)(ubuf[8]) << 48) | ((uint64_t)(ubuf[7]) << 40) frequency = ((uint64_t) (ubuf[9]) << 56) |
| ((uint64_t)(ubuf[6]) << 32) | ((uint64_t)(ubuf[5]) << 24) | ((uint64_t)(ubuf[4]) << 16) ((uint64_t) (ubuf[8]) << 48) |
| ((uint64_t)(ubuf[3]) << 8) | ubuf[2]; ((uint64_t) (ubuf[7]) << 40) |
((uint64_t) (ubuf[6]) << 32) |
((uint64_t) (ubuf[5]) << 24) |
((uint64_t) (ubuf[4]) << 16) |
((uint64_t) (ubuf[3]) << 8) | ubuf[2];
} else { } else {
buf += BYTES_PER_BLOCK; buf += BYTES_PER_BLOCK;
continue; continue;
@ -242,15 +254,20 @@ int rx_callback(hackrf_transfer* transfer) {
for (i = 0; i < ifft_bins; i++) { for (i = 0; i < ifft_bins; i++) {
ifftwOut[i][0] *= 1.0f / ifft_bins; ifftwOut[i][0] *= 1.0f / ifft_bins;
ifftwOut[i][1] *= 1.0f / ifft_bins; ifftwOut[i][1] *= 1.0f / ifft_bins;
fwrite(&ifftwOut[i][0], sizeof(float), 1, outfile); fwrite(&ifftwOut[i][0],
fwrite(&ifftwOut[i][1], sizeof(float), 1, outfile); sizeof(float),
1,
outfile);
fwrite(&ifftwOut[i][1],
sizeof(float),
1,
outfile);
} }
} }
sweep_count++; sweep_count++;
if (one_shot) { if (one_shot) {
do_exit = true; do_exit = true;
} } else if (finite_mode && sweep_count == num_sweeps) {
else if(finite_mode && sweep_count == num_sweeps) {
do_exit = true; do_exit = true;
} }
} }
@ -279,15 +296,18 @@ int rx_callback(hackrf_transfer* transfer) {
pwr[i] = logPower(fftwOut[i], 1.0f / fftSize); pwr[i] = logPower(fftwOut[i], 1.0f / fftSize);
} }
if (binary_output) { if (binary_output) {
record_length = 2 * sizeof(band_edge) record_length =
+ (fftSize/4) * sizeof(float); 2 * sizeof(band_edge) + (fftSize / 4) * sizeof(float);
fwrite(&record_length, sizeof(record_length), 1, outfile); fwrite(&record_length, sizeof(record_length), 1, outfile);
band_edge = frequency; band_edge = frequency;
fwrite(&band_edge, sizeof(band_edge), 1, outfile); fwrite(&band_edge, sizeof(band_edge), 1, outfile);
band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 4; band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 4;
fwrite(&band_edge, sizeof(band_edge), 1, outfile); fwrite(&band_edge, sizeof(band_edge), 1, outfile);
fwrite(&pwr[1+(fftSize*5)/8], sizeof(float), fftSize/4, outfile); fwrite(&pwr[1 + (fftSize * 5) / 8],
sizeof(float),
fftSize / 4,
outfile);
fwrite(&record_length, sizeof(record_length), 1, outfile); fwrite(&record_length, sizeof(record_length), 1, outfile);
band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 2; band_edge = frequency + DEFAULT_SAMPLE_RATE_HZ / 2;
@ -296,24 +316,30 @@ int rx_callback(hackrf_transfer* transfer) {
fwrite(&band_edge, sizeof(band_edge), 1, outfile); fwrite(&band_edge, sizeof(band_edge), 1, outfile);
fwrite(&pwr[1 + fftSize / 8], sizeof(float), fftSize / 4, outfile); fwrite(&pwr[1 + fftSize / 8], sizeof(float), fftSize / 4, outfile);
} else if (ifft_output) { } else if (ifft_output) {
ifft_idx = (uint32_t) round((frequency - (uint64_t)(FREQ_ONE_MHZ*frequencies[0])) ifft_idx = (uint32_t) round(
/ fft_bin_width); (frequency - (uint64_t) (FREQ_ONE_MHZ * frequencies[0])) /
fft_bin_width);
ifft_idx = (ifft_idx + ifft_bins / 2) % ifft_bins; ifft_idx = (ifft_idx + ifft_bins / 2) % ifft_bins;
for (i = 0; (fftSize / 4) > i; i++) { for (i = 0; (fftSize / 4) > i; i++) {
ifftwIn[ifft_idx + i][0] = fftwOut[i + 1 + (fftSize*5)/8][0]; ifftwIn[ifft_idx + i][0] =
ifftwIn[ifft_idx + i][1] = fftwOut[i + 1 + (fftSize*5)/8][1]; fftwOut[i + 1 + (fftSize * 5) / 8][0];
ifftwIn[ifft_idx + i][1] =
fftwOut[i + 1 + (fftSize * 5) / 8][1];
} }
ifft_idx += fftSize / 2; ifft_idx += fftSize / 2;
ifft_idx %= ifft_bins; ifft_idx %= ifft_bins;
for (i = 0; (fftSize / 4) > i; i++) { for (i = 0; (fftSize / 4) > i; i++) {
ifftwIn[ifft_idx + i][0] = fftwOut[i + 1 + (fftSize/8)][0]; ifftwIn[ifft_idx + i][0] =
ifftwIn[ifft_idx + i][1] = fftwOut[i + 1 + (fftSize/8)][1]; fftwOut[i + 1 + (fftSize / 8)][0];
ifftwIn[ifft_idx + i][1] =
fftwOut[i + 1 + (fftSize / 8)][1];
} }
} else { } else {
time_t time_stamp_seconds = usb_transfer_time.tv_sec; time_t time_stamp_seconds = usb_transfer_time.tv_sec;
fft_time = localtime(&time_stamp_seconds); fft_time = localtime(&time_stamp_seconds);
strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time); strftime(time_str, 50, "%Y-%m-%d, %H:%M:%S", fft_time);
fprintf(outfile, "%s.%06ld, %" PRIu64 ", %" PRIu64 ", %.2f, %u", fprintf(outfile,
"%s.%06ld, %" PRIu64 ", %" PRIu64 ", %.2f, %u",
time_str, time_str,
(long int) usb_transfer_time.tv_usec, (long int) usb_transfer_time.tv_usec,
(uint64_t) (frequency), (uint64_t) (frequency),
@ -321,10 +347,13 @@ int rx_callback(hackrf_transfer* transfer) {
fft_bin_width, fft_bin_width,
fftSize); fftSize);
for (i = 0; (fftSize / 4) > i; i++) { for (i = 0; (fftSize / 4) > i; i++) {
fprintf(outfile, ", %.2f", pwr[i + 1 + (fftSize*5)/8]); fprintf(outfile,
", %.2f",
pwr[i + 1 + (fftSize * 5) / 8]);
} }
fprintf(outfile, "\n"); fprintf(outfile, "\n");
fprintf(outfile, "%s.%06ld, %" PRIu64 ", %" PRIu64 ", %.2f, %u", fprintf(outfile,
"%s.%06ld, %" PRIu64 ", %" PRIu64 ", %.2f, %u",
time_str, time_str,
(long int) usb_transfer_time.tv_usec, (long int) usb_transfer_time.tv_usec,
(uint64_t) (frequency + (DEFAULT_SAMPLE_RATE_HZ / 2)), (uint64_t) (frequency + (DEFAULT_SAMPLE_RATE_HZ / 2)),
@ -340,31 +369,33 @@ int rx_callback(hackrf_transfer* transfer) {
return 0; return 0;
} }
static void usage() { static void usage()
fprintf(stderr, "Usage:\n"); {
fprintf(stderr, "\t[-h] # this help\n"); fprintf(stderr,
fprintf(stderr, "\t[-d serial_number] # Serial number of desired HackRF\n"); "Usage:\n"
fprintf(stderr, "\t[-a amp_enable] # RX RF amplifier 1=Enable, 0=Disable\n"); "\t[-h] # this help\n"
fprintf(stderr, "\t[-f freq_min:freq_max] # minimum and maximum frequencies in MHz\n"); "\t[-d serial_number] # Serial number of desired HackRF\n"
fprintf(stderr, "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable\n"); "\t[-a amp_enable] # RX RF amplifier 1=Enable, 0=Disable\n"
fprintf(stderr, "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"); "\t[-f freq_min:freq_max] # minimum and maximum frequencies in MHz\n"
fprintf(stderr, "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"); "\t[-p antenna_enable] # Antenna port power, 1=Enable, 0=Disable\n"
fprintf(stderr, "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz, 2445-5000000\n"); "\t[-l gain_db] # RX LNA (IF) gain, 0-40dB, 8dB steps\n"
fprintf(stderr, "\t[-1] # one shot mode\n"); "\t[-g gain_db] # RX VGA (baseband) gain, 0-62dB, 2dB steps\n"
fprintf(stderr, "\t[-N num_sweeps] # Number of sweeps to perform\n"); "\t[-w bin_width] # FFT bin width (frequency resolution) in Hz, 2445-5000000\n"
fprintf(stderr, "\t[-B] # binary output\n"); "\t[-1] # one shot mode\n"
fprintf(stderr, "\t[-I] # binary inverse FFT output\n"); "\t[-N num_sweeps] # Number of sweeps to perform\n"
fprintf(stderr, "\t-r filename # output file\n"); "\t[-B] # binary output\n"
fprintf(stderr, "\n"); "\t[-I] # binary inverse FFT output\n"
fprintf(stderr, "Output fields:\n"); "\t-r filename # output file\n"
fprintf(stderr, "\tdate, time, hz_low, hz_high, hz_bin_width, num_samples, dB, dB, . . .\n"); "\n"
"Output fields:\n"
"\tdate, time, hz_low, hz_high, hz_bin_width, num_samples, dB, dB, . . .\n");
} }
static hackrf_device* device = NULL; static hackrf_device* device = NULL;
#ifdef _MSC_VER #ifdef _MSC_VER
BOOL WINAPI BOOL WINAPI sighandler(int signum)
sighandler(int signum) { {
if (CTRL_C_EVENT == signum) { if (CTRL_C_EVENT == signum) {
fprintf(stderr, "Caught signal %d\n", signum); fprintf(stderr, "Caught signal %d\n", signum);
do_exit = true; do_exit = true;
@ -373,13 +404,15 @@ sighandler(int signum) {
return FALSE; return FALSE;
} }
#else #else
void sigint_callback_handler(int signum) { void sigint_callback_handler(int signum)
{
fprintf(stderr, "Caught signal %d\n", signum); fprintf(stderr, "Caught signal %d\n", signum);
do_exit = true; do_exit = true;
} }
#endif #endif
int main(int argc, char** argv) { int main(int argc, char** argv)
{
int opt, i, result = 0; int opt, i, result = 0;
const char* path = NULL; const char* path = NULL;
const char* serial_number = NULL; const char* serial_number = NULL;
@ -393,11 +426,9 @@ int main(int argc, char** argv) {
uint32_t freq_max = 6000; uint32_t freq_max = 6000;
uint32_t requested_fft_bin_width; uint32_t requested_fft_bin_width;
while ((opt = getopt(argc, argv, "a:f:p:l:g:d:n:N:w:1BIr:h?")) != EOF) { while ((opt = getopt(argc, argv, "a:f:p:l:g:d:n:N:w:1BIr:h?")) != EOF) {
result = HACKRF_SUCCESS; result = HACKRF_SUCCESS;
switch( opt ) switch (opt) {
{
case 'd': case 'd':
serial_number = optarg; serial_number = optarg;
break; break;
@ -485,17 +516,24 @@ int main(int argc, char** argv) {
} }
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "argument error: '-%c %s' %s (%d)\n", opt, optarg, hackrf_error_name(result), result); fprintf(stderr,
"argument error: '-%c %s' %s (%d)\n",
opt,
optarg,
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
} }
if (lna_gain % 8) if (lna_gain % 8) {
fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n"); fprintf(stderr, "warning: lna_gain (-l) must be a multiple of 8\n");
}
if (vga_gain % 2) if (vga_gain % 2) {
fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n"); fprintf(stderr, "warning: vga_gain (-g) must be a multiple of 2\n");
}
if (amp) { if (amp) {
if (amp_enable > 1) { if (amp_enable > 1) {
@ -507,7 +545,8 @@ int main(int argc, char** argv) {
if (antenna) { if (antenna) {
if (antenna_enable > 1) { if (antenna_enable > 1) {
fprintf(stderr, "argument error: antenna_enable shall be 0 or 1.\n"); fprintf(stderr,
"argument error: antenna_enable shall be 0 or 1.\n");
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -520,12 +559,14 @@ int main(int argc, char** argv) {
} }
if (binary_output && ifft_output) { if (binary_output && ifft_output) {
fprintf(stderr, "argument error: binary output (-B) and IFFT output (-I) are mutually exclusive.\n"); fprintf(stderr,
"argument error: binary output (-B) and IFFT output (-I) are mutually exclusive.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (ifft_output && (1 < num_ranges)) { if (ifft_output && (1 < num_ranges)) {
fprintf(stderr, "argument error: only one frequency range is supported in IFFT output (-I) mode.\n"); fprintf(stderr,
"argument error: only one frequency range is supported in IFFT output (-I) mode.\n");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -565,7 +606,8 @@ int main(int argc, char** argv) {
fft_bin_width = (double) DEFAULT_SAMPLE_RATE_HZ / fftSize; fft_bin_width = (double) DEFAULT_SAMPLE_RATE_HZ / fftSize;
fftwIn = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); fftwIn = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fftwOut = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize); fftwOut = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
fftwPlan = fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE); fftwPlan =
fftwf_plan_dft_1d(fftSize, fftwIn, fftwOut, FFTW_FORWARD, FFTW_MEASURE);
pwr = (float*) fftwf_malloc(sizeof(float) * fftSize); pwr = (float*) fftwf_malloc(sizeof(float) * fftSize);
window = (float*) fftwf_malloc(sizeof(float) * fftSize); window = (float*) fftwf_malloc(sizeof(float) * fftSize);
for (i = 0; i < fftSize; i++) { for (i = 0; i < fftSize; i++) {
@ -580,14 +622,20 @@ int main(int argc, char** argv) {
result = hackrf_init(); result = hackrf_init();
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init() failed: %s (%d)\n", hackrf_error_name(result), result); fprintf(stderr,
"hackrf_init() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result = hackrf_open_by_serial(serial_number, &device); result = hackrf_open_by_serial(serial_number, &device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_open() failed: %s (%d)\n", hackrf_error_name(result), result); fprintf(stderr,
"hackrf_open() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -620,22 +668,30 @@ int main(int argc, char** argv) {
signal(SIGTERM, &sigint_callback_handler); signal(SIGTERM, &sigint_callback_handler);
signal(SIGABRT, &sigint_callback_handler); signal(SIGABRT, &sigint_callback_handler);
#endif #endif
fprintf(stderr, "call hackrf_sample_rate_set(%.03f MHz)\n", fprintf(stderr,
"call hackrf_sample_rate_set(%.03f MHz)\n",
((float) DEFAULT_SAMPLE_RATE_HZ / (float) FREQ_ONE_MHZ)); ((float) DEFAULT_SAMPLE_RATE_HZ / (float) FREQ_ONE_MHZ));
result = hackrf_set_sample_rate_manual(device, DEFAULT_SAMPLE_RATE_HZ, 1); result = hackrf_set_sample_rate_manual(device, DEFAULT_SAMPLE_RATE_HZ, 1);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_sample_rate_set() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_sample_rate_set() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
fprintf(stderr, "call hackrf_baseband_filter_bandwidth_set(%.03f MHz)\n", fprintf(stderr,
"call hackrf_baseband_filter_bandwidth_set(%.03f MHz)\n",
((float) DEFAULT_BASEBAND_FILTER_BANDWIDTH / (float) FREQ_ONE_MHZ)); ((float) DEFAULT_BASEBAND_FILTER_BANDWIDTH / (float) FREQ_ONE_MHZ));
result = hackrf_set_baseband_filter_bandwidth(device, DEFAULT_BASEBAND_FILTER_BANDWIDTH); result = hackrf_set_baseband_filter_bandwidth(
device,
DEFAULT_BASEBAND_FILTER_BANDWIDTH);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_baseband_filter_bandwidth_set() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -649,30 +705,51 @@ int main(int argc, char** argv) {
* whole number of steps, minimum 1. * whole number of steps, minimum 1.
*/ */
for (i = 0; i < num_ranges; i++) { for (i = 0; i < num_ranges; i++) {
step_count = 1 + (frequencies[2*i+1] - frequencies[2*i] - 1) step_count =
/ TUNE_STEP; 1 + (frequencies[2 * i + 1] - frequencies[2 * i] - 1) / TUNE_STEP;
frequencies[2*i+1] = (uint16_t) (frequencies[2*i] + step_count * TUNE_STEP); frequencies[2 * i + 1] =
fprintf(stderr, "Sweeping from %u MHz to %u MHz\n", (uint16_t) (frequencies[2 * i] + step_count * TUNE_STEP);
frequencies[2*i], frequencies[2*i+1]); fprintf(stderr,
"Sweeping from %u MHz to %u MHz\n",
frequencies[2 * i],
frequencies[2 * i + 1]);
} }
if (ifft_output) { if (ifft_output) {
ifftwIn = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize * step_count); ifftwIn = (fftwf_complex*) fftwf_malloc(
ifftwOut = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * fftSize * step_count); sizeof(fftwf_complex) * fftSize * step_count);
ifftwPlan = fftwf_plan_dft_1d(fftSize * step_count, ifftwIn, ifftwOut, FFTW_BACKWARD, FFTW_MEASURE); ifftwOut = (fftwf_complex*) fftwf_malloc(
sizeof(fftwf_complex) * fftSize * step_count);
ifftwPlan = fftwf_plan_dft_1d(
fftSize * step_count,
ifftwIn,
ifftwOut,
FFTW_BACKWARD,
FFTW_MEASURE);
} }
result = hackrf_init_sweep(device, frequencies, num_ranges, BYTES_PER_BLOCK, result = hackrf_init_sweep(
TUNE_STEP * FREQ_ONE_MHZ, OFFSET, INTERLEAVED); device,
frequencies,
num_ranges,
BYTES_PER_BLOCK,
TUNE_STEP * FREQ_ONE_MHZ,
OFFSET,
INTERLEAVED);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_init_sweep() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_init_sweep() failed: %s (%d)\n",
hackrf_error_name(result),
result);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
result |= hackrf_start_rx_sweep(device, rx_callback, NULL); result |= hackrf_start_rx_sweep(device, rx_callback, NULL);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_start_rx_sweep() failed: %s (%d)\n", hackrf_error_name(result), result); fprintf(stderr,
"hackrf_start_rx_sweep() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -681,8 +758,10 @@ int main(int argc, char** argv) {
fprintf(stderr, "call hackrf_set_amp_enable(%u)\n", amp_enable); fprintf(stderr, "call hackrf_set_amp_enable(%u)\n", amp_enable);
result = hackrf_set_amp_enable(device, (uint8_t) amp_enable); result = hackrf_set_amp_enable(device, (uint8_t) amp_enable);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_set_amp_enable() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_set_amp_enable() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -692,8 +771,10 @@ int main(int argc, char** argv) {
fprintf(stderr, "call hackrf_set_antenna_enable(%u)\n", antenna_enable); fprintf(stderr, "call hackrf_set_antenna_enable(%u)\n", antenna_enable);
result = hackrf_set_antenna_enable(device, (uint8_t) antenna_enable); result = hackrf_set_antenna_enable(device, (uint8_t) antenna_enable);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_set_antenna_enable() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_set_antenna_enable() failed: %s (%d)\n",
hackrf_error_name(result),
result);
usage(); usage();
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -711,12 +792,16 @@ int main(int argc, char** argv) {
if (TimevalDiff(&time_now, &time_prev) >= 1.0f) { if (TimevalDiff(&time_now, &time_prev) >= 1.0f) {
time_difference = TimevalDiff(&time_now, &t_start); time_difference = TimevalDiff(&time_now, &t_start);
sweep_rate = (float) sweep_count / time_difference; sweep_rate = (float) sweep_count / time_difference;
fprintf(stderr, "%" PRIu64 " total sweeps completed, %.2f sweeps/second\n", fprintf(stderr,
sweep_count, sweep_rate); "%" PRIu64
" total sweeps completed, %.2f sweeps/second\n",
sweep_count,
sweep_rate);
if (byte_count == 0) { if (byte_count == 0) {
exit_code = EXIT_FAILURE; exit_code = EXIT_FAILURE;
fprintf(stderr, "\nCouldn't transfer any data for one second.\n"); fprintf(stderr,
"\nCouldn't transfer any data for one second.\n");
break; break;
} }
byte_count = 0; byte_count = 0;
@ -729,22 +814,30 @@ int main(int argc, char** argv) {
if (do_exit) { if (do_exit) {
fprintf(stderr, "\nExiting...\n"); fprintf(stderr, "\nExiting...\n");
} else { } else {
fprintf(stderr, "\nExiting... hackrf_is_streaming() result: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "\nExiting... hackrf_is_streaming() result: %s (%d)\n",
hackrf_error_name(result),
result);
} }
gettimeofday(&time_now, NULL); gettimeofday(&time_now, NULL);
time_diff = TimevalDiff(&time_now, &t_start); time_diff = TimevalDiff(&time_now, &t_start);
if((sweep_rate == 0) && (time_diff > 0)) if ((sweep_rate == 0) && (time_diff > 0)) {
sweep_rate = sweep_count / time_diff; sweep_rate = sweep_count / time_diff;
fprintf(stderr, "Total sweeps: %" PRIu64 " in %.5f seconds (%.2f sweeps/second)\n", }
sweep_count, time_diff, sweep_rate); fprintf(stderr,
"Total sweeps: %" PRIu64 " in %.5f seconds (%.2f sweeps/second)\n",
sweep_count,
time_diff,
sweep_rate);
if (device != NULL) { if (device != NULL) {
result = hackrf_close(device); result = hackrf_close(device);
if (result != HACKRF_SUCCESS) { if (result != HACKRF_SUCCESS) {
fprintf(stderr, "hackrf_close() failed: %s (%d)\n", fprintf(stderr,
hackrf_error_name(result), result); "hackrf_close() failed: %s (%d)\n",
hackrf_error_name(result),
result);
} else { } else {
fprintf(stderr, "hackrf_close() done\n"); fprintf(stderr, "hackrf_close() done\n");
} }

Some files were not shown because too many files have changed in this diff Show More