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,25 +21,40 @@
#include "bitband.h"
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 byte_offset = (uint32_t)address - 0x40000000;
const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4);
const uint32_t bit_word_address = bit_band_base + bit_word_offset;
return (volatile uint32_t*)bit_word_address;
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 byte_offset = (uint32_t) address - 0x40000000;
const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4);
const uint32_t bit_word_address = bit_band_base + bit_word_offset;
return (volatile uint32_t*) bit_word_address;
}
void peripheral_bitband_set(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;
void peripheral_bitband_set(
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;
}
void peripheral_bitband_clear(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;
void peripheral_bitband_clear(
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;
}
uint32_t peripheral_bitband_get(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;
uint32_t peripheral_bitband_get(
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;
}

View File

@ -24,9 +24,17 @@
#include <stdint.h>
volatile uint32_t* peripheral_bitband_address(volatile void* const 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);
volatile uint32_t* peripheral_bitband_address(
volatile void* const 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 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;
/* 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);
}
void cpld_jtag_release(jtag_t* const jtag) {
void cpld_jtag_release(jtag_t* const jtag)
{
const jtag_gpio_t* const gpio = jtag->gpio;
/* Make all pins inputs when JTAG interface not active.
@ -72,30 +74,31 @@ void cpld_jtag_release(jtag_t* const jtag) {
/* return 0 if success else return error code see xsvfExecute() */
int cpld_jtag_program(
jtag_t* const jtag,
const uint32_t buffer_length,
unsigned char* const buffer,
refill_buffer_cb refill
) {
jtag_t* const jtag,
const uint32_t buffer_length,
unsigned char* const buffer,
refill_buffer_cb refill)
{
int error;
cpld_jtag_take(jtag);
xsvf_buffer = buffer;
xsvf_buffer_len = buffer_length;
refill_buffer = refill;
refill_buffer = refill;
error = xsvfExecute(jtag->gpio);
cpld_jtag_release(jtag);
return error;
}
/* this gets called by the XAPP058 code */
unsigned char cpld_jtag_get_next_byte(void) {
if (xsvf_pos == xsvf_buffer_len) {
refill_buffer();
xsvf_pos = 0;
}
unsigned char cpld_jtag_get_next_byte(void)
{
if (xsvf_pos == xsvf_buffer_len) {
refill_buffer();
xsvf_pos = 0;
}
unsigned char byte = xsvf_buffer[xsvf_pos];
xsvf_pos++;
xsvf_pos++;
return byte;
}

View File

@ -52,11 +52,10 @@ void cpld_jtag_release(jtag_t* const jtag);
* contents of the buffer has been streamed to the CPLD the given
* refill_buffer callback will be called. */
int cpld_jtag_program(
jtag_t* const jtag,
const uint32_t buffer_length,
unsigned char* const buffer,
refill_buffer_cb refill
);
jtag_t* const jtag,
const uint32_t buffer_length,
unsigned char* const buffer,
refill_buffer_cb refill);
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 <string.h>
// clang-format off
typedef enum {
CPLD_XC2C_IR_INTEST = 0b00000010,
CPLD_XC2C_IR_BYPASS = 0b11111111,
@ -53,7 +54,13 @@ typedef enum {
CPLD_XC2C_IR_ISC_NOOP = 0b11100000,
} 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
gpio_write(jtag->gpio->gpio_tdi, tdi);
gpio_write(jtag->gpio->gpio_tms, tms);
@ -76,7 +83,7 @@ static bool cpld_xc2c_jtag_clock(const jtag_t* const jtag, const uint32_t tms, c
__asm__("nop");
__asm__("nop");
__asm__("nop");
gpio_set(jtag->gpio->gpio_tck);
// 15 ns TCK to TMS/TDI hold time
@ -88,30 +95,46 @@ static bool cpld_xc2c_jtag_clock(const jtag_t* const jtag, const uint32_t tms, c
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) {
for(size_t i=start; i<end; i++) {
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++) {
const size_t byte_n = i >> 3;
const size_t bit_n = i & 7;
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] |= (tdo << bit_n);
}
}
static void cpld_xc2c_jtag_shift_ptr(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t count) {
if( count > 0 ) {
static void cpld_xc2c_jtag_shift_ptr(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t count)
{
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, 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;
for(size_t i=0; i<count; i++) {
for (size_t i = 0; i < count; i++) {
const uint32_t mask = (1U << i);
tdo |= cpld_xc2c_jtag_clock(jtag, tms & mask, tdi & mask) << i;
}
@ -119,24 +142,31 @@ static uint32_t cpld_xc2c_jtag_shift_u32(const jtag_t* const jtag, const uint32_
return tdo;
}
static void cpld_xc2c_jtag_clocks(const jtag_t* const jtag, const size_t count) {
for(size_t i=0; i<count; i++) {
static void cpld_xc2c_jtag_clocks(const jtag_t* const jtag, const size_t count)
{
for (size_t i = 0; i < count; i++) {
cpld_xc2c_jtag_clock(jtag, 0, 0);
}
}
static void cpld_xc2c_jtag_pause(const jtag_t* const jtag, const size_t count) {
for(size_t i=0; i<count; i++) {
static void cpld_xc2c_jtag_pause(const jtag_t* const jtag, const size_t count)
{
for (size_t i = 0; i < count; i++) {
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 */
cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3);
/* Shift-[DI]R -> Exit1-[DI]R */
cpld_xc2c_jtag_shift_ptr(jtag, tdi_tdo, bit_count);
if( pause_count ) {
if (pause_count) {
/* Exit1-[DI]R -> Pause-[DI]R */
cpld_xc2c_jtag_shift_u32(jtag, 0b0, 0, 1);
/* Pause-[DI]R -> Exit2-[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);
}
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);
}
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 */
cpld_xc2c_jtag_shift_u32(jtag, 0b1, 0b0, 1);
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;
}
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);
}
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.
*/
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.
* One TMS=0 to move from Test-Logic-Reset to Run-Test-Idle.
*/
@ -176,60 +218,71 @@ static void cpld_xc2c_jtag_reset_and_idle(const jtag_t* const jtag) {
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. */
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_IDCODE);
uint32_t result = 0;
cpld_xc2c_jtag_shift_dr(jtag, (uint8_t*)&result, 32, 0);
cpld_xc2c_jtag_shift_dr(jtag, (uint8_t*) &result, 32, 0);
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;
}
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_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_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_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);
}
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);
}
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);
if( shift_dr ) {
if (shift_dr) {
uint8_t dr = 0;
cpld_xc2c_jtag_shift_dr(jtag, &dr, 1, 0);
}
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. */
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;
}
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_clocks(jtag, 20);
/* 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);
}
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);
}
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_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(
const jtag_t* const jtag,
const cpld_xc2c64a_verify_t* const verify,
uint32_t* const crc_value
) {
uint32_t* const crc_value)
{
cpld_xc2c_jtag_reset_and_idle(jtag);
if( cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_read_write_protect(jtag) &&
cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_read_write_protect(jtag) ) {
if (cpld_xc2c64a_jtag_idcode_ok(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_enable(jtag);
@ -281,12 +340,12 @@ bool cpld_xc2c64a_jtag_checksum(
crc32_init(&crc);
uint8_t dr[CPLD_XC2C64A_BYTES_IN_ROW];
for(size_t row=0; row<CPLD_XC2C64A_ROWS; row++) {
for (size_t row = 0; row < CPLD_XC2C64A_ROWS; row++) {
const size_t address = cpld_hackrf_row_addresses.address[row];
cpld_xc2c64a_jtag_read_row(jtag, address, dr);
const size_t mask_index = verify->mask_index[row];
for(size_t i=0; i<CPLD_XC2C64A_BYTES_IN_ROW; i++) {
for (size_t i = 0; i < CPLD_XC2C64A_BYTES_IN_ROW; i++) {
dr[i] &= verify->mask[mask_index].value[i];
}
@ -303,7 +362,7 @@ bool cpld_xc2c64a_jtag_checksum(
cpld_xc2c_jtag_init_special(jtag);
cpld_xc2c_jtag_conld(jtag);
if( cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_is_done(jtag) ) {
if (cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_is_done(jtag)) {
cpld_xc2c_jtag_conld(jtag);
cpld_xc2c_jtag_bypass(jtag, false);
cpld_xc2c_jtag_bypass(jtag, true);
@ -317,7 +376,11 @@ bool cpld_xc2c64a_jtag_checksum(
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];
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);
}
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 */
cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3);
@ -351,16 +418,22 @@ 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);
}
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 */
uint8_t read[CPLD_XC2C64A_BYTES_IN_ROW];
memset(read, 0xff, sizeof(read));
cpld_xc2c64a_jtag_sram_read_row(jtag, &read[0], next_address);
bool matched = true;
if( (expected != NULL) && (mask != NULL) ) {
for(size_t i=0; i<CPLD_XC2C64A_BYTES_IN_ROW; i++) {
const uint8_t significant_differences = (read[i] ^ expected[i]) & mask[i];
if ((expected != NULL) && (mask != NULL)) {
for (size_t i = 0; i < CPLD_XC2C64A_BYTES_IN_ROW; i++) {
const uint8_t significant_differences =
(read[i] ^ expected[i]) & mask[i];
matched &= (significant_differences == 0);
}
}
@ -370,16 +443,19 @@ static bool cpld_xc2c64a_jtag_sram_compare_row(const jtag_t* const jtag, const u
void cpld_xc2c64a_jtag_sram_write(
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_enable(jtag);
cpld_xc2c_jtag_sram_write(jtag);
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];
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);
@ -390,8 +466,8 @@ void cpld_xc2c64a_jtag_sram_write(
bool cpld_xc2c64a_jtag_sram_verify(
const jtag_t* const jtag,
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_enable(jtag);
@ -401,13 +477,22 @@ bool cpld_xc2c64a_jtag_sram_verify(
* the first row's data.
*/
bool matched = true;
for(size_t address_row=0; address_row<=CPLD_XC2C64A_ROWS; address_row++) {
const int data_row = (int)address_row - 1;
const size_t mask_index = (data_row >= 0) ? verify->mask_index[data_row] : 0;
const uint8_t* const expected = (data_row >= 0) ? &program->row[data_row].data[0] : NULL;
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);
for (size_t address_row = 0; address_row <= CPLD_XC2C64A_ROWS; address_row++) {
const int data_row = (int) address_row - 1;
const size_t mask_index =
(data_row >= 0) ? verify->mask_index[data_row] : 0;
const uint8_t* const expected =
(data_row >= 0) ? &program->row[data_row].data[0] : NULL;
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);

View File

@ -28,8 +28,8 @@
#include "cpld_jtag.h"
/* Xilinx CoolRunner II XC2C64A bitstream attributes */
#define CPLD_XC2C64A_ROWS (98)
#define CPLD_XC2C64A_BITS_IN_ROW (274)
#define CPLD_XC2C64A_ROWS (98)
#define CPLD_XC2C64A_BITS_IN_ROW (274)
#define CPLD_XC2C64A_BYTES_IN_ROW ((CPLD_XC2C64A_BITS_IN_ROW + 7) / 8)
typedef struct {
@ -56,20 +56,17 @@ typedef struct {
bool cpld_xc2c64a_jtag_checksum(
const jtag_t* const jtag,
const cpld_xc2c64a_verify_t* const verify,
uint32_t* const crc_value
);
uint32_t* const crc_value);
void cpld_xc2c64a_jtag_sram_write(
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(
const jtag_t* const jtag,
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_verify_t cpld_hackrf_verify;
extern const cpld_xc2c64a_row_addresses_t cpld_hackrf_row_addresses;
#endif/*__CPLD_XC2C_H__*/
#endif /*__CPLD_XC2C_H__*/

View File

@ -23,27 +23,30 @@
#include <stdbool.h>
void crc32_init(crc32_t* const crc) {
void crc32_init(crc32_t* const crc)
{
crc->remainder = 0xffffffff;
crc->reversed_polynomial = 0xedb88320;
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;
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++) {
const bool bit_in = data[bit_n >> 3] & (1 << (bit_n & 7));
remainder ^= (bit_in ? 1 : 0);
const bool bit_out = (remainder & 1);
remainder >>= 1;
if( bit_out ) {
if (bit_out) {
remainder ^= crc->reversed_polynomial;
}
}
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;
}

View File

@ -35,4 +35,4 @@ void crc32_init(crc32_t* const crc);
void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t byte_count);
uint32_t crc32_digest(const crc32_t* const crc);
#endif//__CRC_H__
#endif //__CRC_H__

View File

@ -24,20 +24,19 @@
#include "fault_handler.h"
typedef struct
{
typedef struct {
uint32_t r0;
uint32_t r1;
uint32_t r2;
uint32_t r3;
uint32_t r12;
uint32_t lr; /* Link Register. */
uint32_t pc; /* Program Counter. */
uint32_t psr;/* Program Status Register. */
uint32_t lr; /* Link Register. */
uint32_t pc; /* Program Counter. */
uint32_t psr; /* Program Status Register. */
} hard_fault_stack_t;
__attribute__((naked))
void hard_fault_handler(void) {
__attribute__((naked)) void hard_fault_handler(void)
{
__asm__("TST LR, #4");
__asm__("ITE EQ");
__asm__("MRSEQ R0, MSP");
@ -47,11 +46,11 @@ void hard_fault_handler(void) {
volatile hard_fault_stack_t* hard_fault_stack_pt;
__attribute__((used)) void hard_fault_handler_c(uint32_t* args)
__attribute__((used)) void hard_fault_handler_c(uint32_t* args)
{
/* hard_fault_stack_pt contains registers saved before the hard fault */
hard_fault_stack_pt = (hard_fault_stack_t*)args;
hard_fault_stack_pt = (hard_fault_stack_t*) args;
// args[0-7]: r0, r1, r2, r3, r12, lr, pc, psr
// Other interesting registers to examine:
// CFSR: Configurable Fault Status Register
@ -60,7 +59,7 @@ __attribute__((used)) void hard_fault_handler_c(uint32_t* args)
// AFSR: Auxiliary Fault Status Register
// MMAR: MemManage Fault Address Register
// BFAR: Bus Fault Address Register
/*
if( SCB->HFSR & SCB_HFSR_FORCED ) {
if( SCB->CFSR & SCB_CFSR_BFSR_BFARVALID ) {
@ -70,17 +69,20 @@ __attribute__((used)) void hard_fault_handler_c(uint32_t* args)
}
}
*/
while(1);
while (1) {}
}
void mem_manage_handler() {
while(1);
void mem_manage_handler()
{
while (1) {}
}
void bus_fault_handler() {
while(1);
void bus_fault_handler()
{
while (1) {}
}
void usage_fault_handler() {
while(1);
void usage_fault_handler()
{
while (1) {}
}

View File

@ -30,6 +30,7 @@
// structures are supposedly the same between processors (to an
// undetermined extent).
typedef struct armv7m_scb_t armv7m_scb_t;
struct armv7m_scb_t {
volatile const uint32_t CPUID;
volatile uint32_t ICSR;
@ -64,10 +65,10 @@ struct armv7m_scb_t {
volatile uint32_t CPACR;
} __attribute__((packed));
static armv7m_scb_t* const SCB = (armv7m_scb_t*)SCB_BASE;
static armv7m_scb_t* const SCB = (armv7m_scb_t*) SCB_BASE;
#define SCB_HFSR_DEBUGEVT (1 << 31)
#define SCB_HFSR_FORCED (1 << 30)
#define SCB_HFSR_VECTTBL (1 << 1)
#define SCB_HFSR_FORCED (1 << 30)
#define SCB_HFSR_VECTTBL (1 << 1)
#endif//__FAULT_HANDLER__
#endif //__FAULT_HANDLER__

View File

@ -23,40 +23,49 @@
#include <libopencm3/lpc43xx/gpdma.h>
void gpdma_controller_enable() {
void gpdma_controller_enable()
{
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);
}
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;
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);
}
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);
}
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);
}
void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count) {
for(size_t i=0; i<lli_count; i++) {
void gpdma_lli_create_loop(gpdma_lli_t* const lli, const size_t lli_count)
{
for (size_t i = 0; i < lli_count; i++) {
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);
lli[lli_count - 1].clli &= ~GPDMA_CLLI_LLI_MASK;
}

View File

@ -40,4 +40,4 @@ void gpdma_lli_enable_interrupt(gpdma_lli_t* const lli);
void gpdma_lli_create_loop(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);
#endif/*__GPDMA_H__*/
#endif /*__GPDMA_H__*/

View File

@ -35,4 +35,4 @@ void gpio_input(gpio_t gpio);
void gpio_write(gpio_t gpio, const bool value);
bool gpio_read(gpio_t gpio);
#endif/*__GPIO_H__*/
#endif /*__GPIO_H__*/

View File

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

View File

@ -32,19 +32,19 @@
*/
typedef struct gpio_port_t {
volatile uint32_t dir; /* +0x000 */
volatile uint32_t dir; /* +0x000 */
uint32_t _reserved0[31];
volatile uint32_t mask; /* +0x080 */
volatile uint32_t mask; /* +0x080 */
uint32_t _reserved1[31];
volatile uint32_t pin; /* +0x100 */
volatile uint32_t pin; /* +0x100 */
uint32_t _reserved2[31];
volatile uint32_t mpin; /* +0x180 */
volatile uint32_t mpin; /* +0x180 */
uint32_t _reserved3[31];
volatile uint32_t set; /* +0x200 */
volatile uint32_t set; /* +0x200 */
uint32_t _reserved4[31];
volatile uint32_t clr; /* +0x280 */
volatile uint32_t clr; /* +0x280 */
uint32_t _reserved5[31];
volatile uint32_t not; /* +0x300 */
volatile uint32_t not ; /* +0x300 */
} gpio_port_t;
struct gpio_t {
@ -53,18 +53,22 @@ struct gpio_t {
volatile uint32_t* const gpio_w;
};
#define GPIO_LPC_BASE (0x400f4000)
#define GPIO_LPC_B_OFFSET (0x0)
#define GPIO_LPC_W_OFFSET (0x1000)
#define GPIO_LPC_BASE (0x400f4000)
#define GPIO_LPC_B_OFFSET (0x0)
#define GPIO_LPC_W_OFFSET (0x1000)
#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_W(_port_num, _pin_num) (volatile uint32_t*)((GPIO_LPC_BASE + GPIO_LPC_W_OFFSET) + ((_port_num) * 0x80) + ((_pin_num) * 4))
#define GPIO_LPC_PORT(_n) \
((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) { \
.mask = (1UL << (_pin_num)), \
.port = GPIO_LPC_PORT(_port_num), \
.gpio_w = GPIO_LPC_W(_port_num, _pin_num), \
}
// clang-format on
#endif/*__GPIO_LPC_H__*/
#endif /*__GPIO_LPC_H__*/

View File

@ -41,110 +41,112 @@
#include <libopencm3/lpc43xx/ssp.h>
#ifdef HACKRF_ONE
#include "portapack.h"
#include "portapack.h"
#endif
#include "gpio_lpc.h"
/* GPIO Output PinMux */
static struct gpio_t gpio_led[] = {
GPIO(2, 1),
GPIO(2, 2),
GPIO(2, 8),
GPIO(2, 1),
GPIO(2, 2),
GPIO(2, 8),
#ifdef RAD1O
GPIO(5, 26),
GPIO(5, 26),
#endif
};
static struct gpio_t gpio_1v8_enable = GPIO(3, 6);
// clang-format off
static struct gpio_t gpio_1v8_enable = GPIO(3, 6);
/* MAX2837 GPIO (XCVR_CTL) PinMux */
static struct gpio_t gpio_max2837_select = GPIO(0, 15);
static struct gpio_t gpio_max2837_enable = GPIO(2, 6);
static struct gpio_t gpio_max2837_rx_enable = GPIO(2, 5);
static struct gpio_t gpio_max2837_tx_enable = GPIO(2, 4);
static struct gpio_t gpio_max2837_select = GPIO(0, 15);
static struct gpio_t gpio_max2837_enable = GPIO(2, 6);
static struct gpio_t gpio_max2837_rx_enable = GPIO(2, 5);
static struct gpio_t gpio_max2837_tx_enable = GPIO(2, 4);
/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */
static struct gpio_t gpio_max5864_select = GPIO(2, 7);
static struct gpio_t gpio_max5864_select = GPIO(2, 7);
/* RFFC5071 GPIO serial interface PinMux */
// #ifdef RAD1O
// 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_data = GPIO(3, 3);
// static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
// 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_data = GPIO(3, 3);
// static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
// #endif
/* RF supply (VAA) control */
#ifdef HACKRF_ONE
static struct gpio_t gpio_vaa_disable = GPIO(2, 9);
static struct gpio_t gpio_vaa_disable = GPIO(2, 9);
#endif
#ifdef RAD1O
static struct gpio_t gpio_vaa_enable = GPIO(2, 9);
static struct gpio_t gpio_vaa_enable = GPIO(2, 9);
#endif
static struct gpio_t gpio_w25q80bv_hold = GPIO(1, 14);
static struct gpio_t gpio_w25q80bv_wp = GPIO(1, 15);
static struct gpio_t gpio_w25q80bv_select = GPIO(5, 11);
static struct gpio_t gpio_w25q80bv_hold = GPIO(1, 14);
static struct gpio_t gpio_w25q80bv_wp = GPIO(1, 15);
static struct gpio_t gpio_w25q80bv_select = GPIO(5, 11);
/* RF switch control */
#ifdef HACKRF_ONE
static struct gpio_t gpio_hp = GPIO(2, 0);
static struct gpio_t gpio_lp = GPIO(2, 10);
static struct gpio_t gpio_tx_mix_bp = GPIO(2, 11);
static struct gpio_t gpio_no_mix_bypass = GPIO(1, 0);
static struct gpio_t gpio_rx_mix_bp = GPIO(2, 12);
static struct gpio_t gpio_tx_amp = GPIO(2, 15);
static struct gpio_t gpio_tx = GPIO(5, 15);
static struct gpio_t gpio_mix_bypass = GPIO(5, 16);
static struct gpio_t gpio_rx = GPIO(5, 5);
static struct gpio_t gpio_no_tx_amp_pwr = GPIO(3, 5);
static struct gpio_t gpio_amp_bypass = GPIO(0, 14);
static struct gpio_t gpio_rx_amp = GPIO(1, 11);
static struct gpio_t gpio_no_rx_amp_pwr = GPIO(1, 12);
static struct gpio_t gpio_hp = GPIO(2, 0);
static struct gpio_t gpio_lp = GPIO(2, 10);
static struct gpio_t gpio_tx_mix_bp = GPIO(2, 11);
static struct gpio_t gpio_no_mix_bypass = GPIO(1, 0);
static struct gpio_t gpio_rx_mix_bp = GPIO(2, 12);
static struct gpio_t gpio_tx_amp = GPIO(2, 15);
static struct gpio_t gpio_tx = GPIO(5, 15);
static struct gpio_t gpio_mix_bypass = GPIO(5, 16);
static struct gpio_t gpio_rx = GPIO(5, 5);
static struct gpio_t gpio_no_tx_amp_pwr = GPIO(3, 5);
static struct gpio_t gpio_amp_bypass = GPIO(0, 14);
static struct gpio_t gpio_rx_amp = GPIO(1, 11);
static struct gpio_t gpio_no_rx_amp_pwr = GPIO(1, 12);
#endif
#ifdef RAD1O
static struct gpio_t gpio_tx_rx_n = GPIO(1, 11);
static struct gpio_t gpio_tx_rx = GPIO(0, 14);
static struct gpio_t gpio_by_mix = GPIO(1, 12);
static struct gpio_t gpio_by_mix_n = GPIO(2, 10);
static struct gpio_t gpio_by_amp = GPIO(1, 0);
static struct gpio_t gpio_by_amp_n = GPIO(5, 5);
static struct gpio_t gpio_mixer_en = GPIO(5, 16);
static struct gpio_t gpio_low_high_filt = GPIO(2, 11);
static struct gpio_t gpio_low_high_filt_n = GPIO(2, 12);
static struct gpio_t gpio_tx_amp = GPIO(2, 15);
static struct gpio_t gpio_rx_lna = GPIO(5, 15);
static struct gpio_t gpio_tx_rx_n = GPIO(1, 11);
static struct gpio_t gpio_tx_rx = GPIO(0, 14);
static struct gpio_t gpio_by_mix = GPIO(1, 12);
static struct gpio_t gpio_by_mix_n = GPIO(2, 10);
static struct gpio_t gpio_by_amp = GPIO(1, 0);
static struct gpio_t gpio_by_amp_n = GPIO(5, 5);
static struct gpio_t gpio_mixer_en = GPIO(5, 16);
static struct gpio_t gpio_low_high_filt = GPIO(2, 11);
static struct gpio_t gpio_low_high_filt_n = GPIO(2, 12);
static struct gpio_t gpio_tx_amp = GPIO(2, 15);
static struct gpio_t gpio_rx_lna = GPIO(5, 15);
#endif
/* CPLD JTAG interface GPIO pins */
static struct gpio_t gpio_cpld_tdo = GPIO(5, 18);
static struct gpio_t gpio_cpld_tck = GPIO(3, 0);
static struct gpio_t gpio_cpld_tdo = GPIO(5, 18);
static struct gpio_t gpio_cpld_tck = GPIO(3, 0);
#if (defined HACKRF_ONE || defined RAD1O)
static struct gpio_t gpio_cpld_tms = GPIO(3, 4);
static struct gpio_t gpio_cpld_tdi = GPIO(3, 1);
static struct gpio_t gpio_cpld_tms = GPIO(3, 4);
static struct gpio_t gpio_cpld_tdi = GPIO(3, 1);
#else
static struct gpio_t gpio_cpld_tms = GPIO(3, 1);
static struct gpio_t gpio_cpld_tdi = GPIO(3, 4);
static struct gpio_t gpio_cpld_tms = GPIO(3, 1);
static struct gpio_t gpio_cpld_tdi = GPIO(3, 4);
#endif
#ifdef HACKRF_ONE
static struct gpio_t gpio_cpld_pp_tms = GPIO(1, 1);
static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8);
static struct gpio_t gpio_cpld_pp_tms = GPIO(1, 1);
static struct gpio_t gpio_cpld_pp_tdo = GPIO(1, 8);
#endif
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_hw_sync_enable = GPIO(5,12);
static struct gpio_t gpio_rx_q_invert = GPIO(0, 13);
// clang-format on
i2c_bus_t i2c0 = {
.obj = (void*)I2C0_BASE,
.obj = (void*) I2C0_BASE,
.start = i2c_lpc_start,
.stop = i2c_lpc_stop,
.transfer = i2c_lpc_transfer,
};
i2c_bus_t i2c1 = {
.obj = (void*)I2C1_BASE,
.obj = (void*) I2C1_BASE,
.start = i2c_lpc_start,
.stop = i2c_lpc_stop,
.transfer = i2c_lpc_transfer,
@ -192,7 +194,7 @@ const ssp_config_t ssp_config_max5864 = {
};
spi_bus_t spi_bus_ssp1 = {
.obj = (void*)SSP1_BASE,
.obj = (void*) SSP1_BASE,
.config = &ssp_config_max2837,
.start = spi_ssp_start,
.stop = spi_ssp_stop,
@ -222,7 +224,7 @@ const ssp_config_t ssp_config_w25q80bv = {
};
spi_bus_t spi_bus_ssp0 = {
.obj = (void*)SSP0_BASE,
.obj = (void*) SSP0_BASE,
.config = &ssp_config_w25q80bv,
.start = spi_ssp_start,
.stop = spi_ssp_stop,
@ -294,46 +296,47 @@ void delay(uint32_t duration)
{
uint32_t i;
for (i = 0; i < duration; i++)
for (i = 0; i < duration; i++) {
__asm__("nop");
}
}
void delay_us_at_mhz(uint32_t us, uint32_t mhz)
{
// The loop below takes 4 cycles per iteration.
uint32_t loop_iterations = (us * mhz) / 4;
asm volatile (
"start%=:\n"
" subs %[ITERATIONS], #1\n" // 1 cycle
" bpl start%=\n" // 3 cycles
:
: [ITERATIONS] "r" (loop_iterations)
);
asm volatile("start%=:\n"
" subs %[ITERATIONS], #1\n" // 1 cycle
" bpl start%=\n" // 3 cycles
:
: [ITERATIONS] "r"(loop_iterations));
}
/* GCD algo from wikipedia */
/* http://en.wikipedia.org/wiki/Greatest_common_divisor */
static uint32_t
gcd(uint32_t u, uint32_t v)
static uint32_t gcd(uint32_t u, uint32_t v)
{
int s;
if (!u || !v)
if (!u || !v) {
return u | v;
}
for (s=0; !((u|v)&1); s++) {
for (s = 0; !((u | v) & 1); s++) {
u >>= 1;
v >>= 1;
}
while (!(u&1))
while (!(u & 1)) {
u >>= 1;
}
do {
while (!(v&1))
while (!(v & 1)) {
v >>= 1;
}
if (u>v) {
if (u > v) {
uint32_t t;
t = v;
v = u;
@ -341,8 +344,7 @@ gcd(uint32_t u, uint32_t v)
}
v = v - u;
}
while (v);
} while (v);
return u << s;
}
@ -350,11 +352,11 @@ gcd(uint32_t u, uint32_t v)
bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
{
const uint64_t VCO_FREQ = 800 * 1000 * 1000; /* 800 MHz */
uint32_t MSx_P1,MSx_P2,MSx_P3;
uint32_t MSx_P1, MSx_P2, MSx_P3;
uint32_t a, b, c;
uint32_t rem;
hackrf_ui()->set_sample_rate(rate_num/2);
hackrf_ui()->set_sample_rate(rate_num / 2);
/* Find best config */
a = (VCO_FREQ * rate_denom) / rate_num;
@ -371,14 +373,14 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
rem /= g;
rate_num /= g;
if (rate_num < (1<<20)) {
if (rate_num < (1 << 20)) {
/* Perfect match */
b = rem;
c = rate_num;
} else {
/* Approximate */
c = (1<<20) - 1;
b = ((uint64_t)c * (uint64_t)rem) / rate_num;
c = (1 << 20) - 1;
b = ((uint64_t) c * (uint64_t) rem) / rate_num;
g = gcd(b, c);
b /= g;
@ -387,30 +389,31 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
}
bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config);
if (streaming) {
sgpio_cpld_stream_disable(&sgpio_config);
sgpio_cpld_stream_disable(&sgpio_config);
}
/* Can we enable integer mode ? */
if (a & 0x1 || b)
if (a & 0x1 || b) {
si5351c_set_int_mode(&clock_gen, 0, 0);
else
} else {
si5351c_set_int_mode(&clock_gen, 0, 1);
}
/* Final MS values */
MSx_P1 = 128*a + (128 * b/c) - 512;
MSx_P2 = (128*b) % c;
MSx_P1 = 128 * a + (128 * b / c) - 512;
MSx_P2 = (128 * b) % c;
MSx_P3 = c;
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0);//p1 doesn't matter
si5351c_configure_multisynth(&clock_gen, 1, 0, 0, 0, 0); //p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0);//p1 doesn't matter
si5351c_configure_multisynth(&clock_gen, 2, 0, 0, 0, 0); //p1 doesn't matter
if (streaming) {
sgpio_cpld_stream_enable(&sgpio_config);
@ -419,73 +422,77 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
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 p2 = 0;
uint32_t p3 = 0;
switch(sample_rate_hz) {
switch (sample_rate_hz) {
case 8000000:
p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec)
p1 = SI_INTDIV(50); // 800MHz / 50 = 16 MHz (SGPIO), 8 MHz (codec)
break;
case 9216000:
// 43.40277777777778: a = 43; b = 29; c = 72
p1 = 5043;
p2 = 40;
p3 = 72;
break;
case 10000000:
p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec)
break;
case 12288000:
// 32.552083333333336: a = 32; b = 159; c = 288
p1 = 3654;
p2 = 192;
p3 = 288;
break;
case 9216000:
// 43.40277777777778: a = 43; b = 29; c = 72
p1 = 5043;
p2 = 40;
p3 = 72;
break;
case 12500000:
p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec)
break;
case 16000000:
p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec)
break;
case 18432000:
// 21.70138888889: a = 21; b = 101; c = 144
p1 = 2265;
p2 = 112;
p3 = 144;
break;
case 10000000:
p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec)
break;
case 12288000:
// 32.552083333333336: a = 32; b = 159; c = 288
p1 = 3654;
p2 = 192;
p3 = 288;
break;
case 12500000:
p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec)
break;
case 16000000:
p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec)
break;
case 18432000:
// 21.70138888889: a = 21; b = 101; c = 144
p1 = 2265;
p2 = 112;
p3 = 144;
break;
case 20000000:
p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec)
break;
case 20000000:
p1 = SI_INTDIV(20); // 800MHz / 20 = 40 MHz (SGPIO), 20 MHz (codec)
break;
default:
return false;
}
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */
si5351c_configure_multisynth(&clock_gen, 1, p1, 0, 1, 0);//p1 doesn't matter
si5351c_configure_multisynth(&clock_gen, 1, p1, 0, 1, 0); //p1 doesn't matter
/* MS0/CLK2 is the source for SGPIO (CODEC_X2_CLK) */
si5351c_configure_multisynth(&clock_gen, 2, p1, 0, 1, 0);//p1 doesn't matter
si5351c_configure_multisynth(&clock_gen, 2, p1, 0, 1, 0); //p1 doesn't matter
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);
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;
}
@ -505,8 +512,7 @@ static void cpu_clock_pll1_max_speed(void)
/* 1. Select the IRC as BASE_M4_CLK source. */
reg_val = CGU_BASE_M4_CLK;
reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK;
reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) |
CGU_BASE_M4_CLK_AUTOBLOCK(1);
reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1);
CGU_BASE_M4_CLK = reg_val;
/* 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
* crystal oscillator as clock source. */
reg_val = CGU_PLL1_CTRL;
// clang-format off
reg_val &= ~( CGU_PLL1_CTRL_CLK_SEL_MASK |
CGU_PLL1_CTRL_PD_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_FBSEL(0) |
CGU_PLL1_CTRL_DIRECT(1);
// clang-format on
CGU_PLL1_CTRL = reg_val;
/* 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). */
CGU_PLL1_CTRL &= ~CGU_PLL1_CTRL_DIRECT_MASK;
@ -559,7 +567,7 @@ static void cpu_clock_pll1_max_speed(void)
}
/* clock startup for LPC4320 configure PLL1 to max speed (204MHz).
Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */
Note: PLL1 clock is used by M4/M0 core, Peripheral, APB1. */
void cpu_clock_init(void)
{
/* use IRC as clock source for APB1 (including I2C0) */
@ -591,9 +599,21 @@ void cpu_clock_init(void)
*/
/* 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 */
/* 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,
4,
20 * 128 - 512,
0,
1,
0); /* 800/20 = 40MHz */
/* 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 */
/* MS6/CLK6 is unused. */
/* MS7/CLK7 is unused. */
@ -624,53 +644,51 @@ void cpu_clock_init(void)
cpu_clock_pll1_max_speed();
/* use XTAL_OSC as clock source for APB1 */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1)
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL);
CGU_BASE_APB1_CLK =
CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL);
/* use XTAL_OSC as clock source for APB3 */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1)
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL);
CGU_BASE_APB3_CLK =
CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL);
/* use XTAL_OSC as clock source for PLL0USB */
CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1)
| CGU_PLL0USB_CTRL_AUTOBLOCK(1)
| CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL);
while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK);
CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_AUTOBLOCK(1) |
CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL);
while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {}
/* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */
/* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */
CGU_PLL0USB_MDIV = 0x06167FFA;
CGU_PLL0USB_NP_DIV = 0x00302062;
CGU_PLL0USB_CTRL |= (CGU_PLL0USB_CTRL_PD(1)
| CGU_PLL0USB_CTRL_DIRECTI(1)
| CGU_PLL0USB_CTRL_DIRECTO(1)
| CGU_PLL0USB_CTRL_CLKEN(1));
CGU_PLL0USB_CTRL |=
(CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_DIRECTI(1) |
CGU_PLL0USB_CTRL_DIRECTO(1) | CGU_PLL0USB_CTRL_CLKEN(1));
/* power on PLL0USB and wait until stable */
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 */
CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1)
| CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB);
CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) |
CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB);
/* Switch peripheral clock over to use PLL1 (204MHz) */
CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1)
| CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) |
CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB1 clock over to use PLL1 (204MHz) */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1)
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_APB1_CLK =
CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB3 clock over to use PLL1 (204MHz) */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1)
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_APB3_CLK =
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_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_SSP0_CLK =
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_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_SSP1_CLK =
CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
#if (defined JAWBREAKER || defined HACKRF_ONE)
/* Disable unused clocks */
@ -685,8 +703,8 @@ void cpu_clock_init(void)
CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1);
/* Base clocks */
CGU_BASE_SPIFI_CLK = CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */
CGU_BASE_USB1_CLK = CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */
CGU_BASE_SPIFI_CLK = CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */
CGU_BASE_USB1_CLK = CGU_BASE_USB1_CLK_PD(1); /* USB1 is not exposed on HackRF */
CGU_BASE_PHY_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1);
CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_CLK_PD(1);
CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1);
@ -745,7 +763,7 @@ clock_source_t activate_best_clock_source(void)
{
#ifdef HACKRF_ONE
/* Ensure PortaPack reference oscillator is off while checking for external clock input. */
if( portapack_reference_oscillator && portapack()) {
if (portapack_reference_oscillator && portapack()) {
portapack_reference_oscillator(false);
}
#endif
@ -758,9 +776,9 @@ clock_source_t activate_best_clock_source(void)
} else {
#ifdef HACKRF_ONE
/* Enable PortaPack reference oscillator (if present), and check for valid clock. */
if( portapack_reference_oscillator && portapack() ) {
if (portapack_reference_oscillator && portapack()) {
portapack_reference_oscillator(true);
delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */
delay(510000); /* loop iterations @ 204MHz for >10ms for oscillator to enable. */
if (si5351c_clkin_signal_valid(&clock_gen)) {
source = CLOCK_SOURCE_PORTAPACK;
} else {
@ -771,7 +789,9 @@ clock_source_t activate_best_clock_source(void)
/* 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);
return source;
}
@ -786,7 +806,8 @@ void ssp1_set_mode_max5864(void)
spi_bus_start(max5864.bus, &ssp_config_max5864);
}
void pin_setup(void) {
void pin_setup(void)
{
/* Configure all GPIO as Input (safe state) */
gpio_init();
@ -805,13 +826,13 @@ void pin_setup(void) {
* LPC43xx pull-up and pull-down resistors are approximately 53K.
*/
#ifdef HACKRF_ONE
scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
#endif
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_PINMUX_CPLD_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
/* Configure SCU Pin Mux as GPIO */
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);
@ -870,23 +891,26 @@ void pin_setup(void) {
mixer_bus_setup(&mixer);
rf_path_pin_setup(&rf_path);
/* Configure external clock in */
scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
sgpio_configure_pin_functions(&sgpio_config);
}
void enable_1v8_power(void) {
void enable_1v8_power(void)
{
gpio_set(&gpio_1v8_enable);
}
void disable_1v8_power(void) {
void disable_1v8_power(void)
{
gpio_clear(&gpio_1v8_enable);
}
#ifdef HACKRF_ONE
void enable_rf_power(void) {
void enable_rf_power(void)
{
uint32_t i;
/* many short pulses to avoid one big voltage glitch */
@ -897,41 +921,48 @@ void enable_rf_power(void) {
gpio_clear(&gpio_vaa_disable);
}
void disable_rf_power(void) {
void disable_rf_power(void)
{
gpio_set(&gpio_vaa_disable);
}
#endif
#ifdef RAD1O
void enable_rf_power(void) {
void enable_rf_power(void)
{
gpio_set(&gpio_vaa_enable);
}
void disable_rf_power(void) {
void disable_rf_power(void)
{
gpio_clear(&gpio_vaa_enable);
}
#endif
void led_on(const led_t led) {
void led_on(const led_t 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]);
}
void led_toggle(const led_t led) {
void led_toggle(const led_t led)
{
gpio_toggle(&gpio_led[led]);
}
void hw_sync_enable(const hw_sync_mode_t hw_sync_mode){
gpio_write(&gpio_hw_sync_enable, hw_sync_mode==1);
void hw_sync_enable(const hw_sync_mode_t hw_sync_mode)
{
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)
{
while (1) {
led_on(LED1);
led_on(LED2);
led_on(LED3);

View File

@ -25,8 +25,7 @@
#define __HACKRF_CORE_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
#include <stdint.h>
@ -49,15 +48,15 @@ extern "C"
#define BOARD_ID_RAD1O 3
#ifdef JAWBREAKER
#define BOARD_ID BOARD_ID_JAWBREAKER
#define BOARD_ID BOARD_ID_JAWBREAKER
#endif
#ifdef HACKRF_ONE
#define BOARD_ID BOARD_ID_HACKRF_ONE
#define BOARD_ID BOARD_ID_HACKRF_ONE
#endif
#ifdef RAD1O
#define BOARD_ID BOARD_ID_RAD1O
#define BOARD_ID BOARD_ID_RAD1O
#endif
/*
@ -65,21 +64,21 @@ extern "C"
*/
/* GPIO Output PinMux */
#define SCU_PINMUX_LED1 (P4_1) /* GPIO2[1] on P4_1 */
#define SCU_PINMUX_LED2 (P4_2) /* GPIO2[2] on P4_2 */
#define SCU_PINMUX_LED3 (P6_12) /* GPIO2[8] on P6_12 */
#define SCU_PINMUX_LED1 (P4_1) /* GPIO2[1] on P4_1 */
#define SCU_PINMUX_LED2 (P4_2) /* GPIO2[2] on P4_2 */
#define SCU_PINMUX_LED3 (P6_12) /* GPIO2[8] on P6_12 */
#ifdef RAD1O
#define SCU_PINMUX_LED4 (PB_6) /* GPIO5[26] on PB_6 */
#define SCU_PINMUX_LED4 (PB_6) /* GPIO5[26] on PB_6 */
#endif
#define SCU_PINMUX_EN1V8 (P6_10) /* GPIO3[6] on P6_10 */
#define SCU_PINMUX_EN1V8 (P6_10) /* GPIO3[6] on P6_10 */
/* GPIO Input PinMux */
#define SCU_PINMUX_BOOT0 (P1_1) /* GPIO0[8] on P1_1 */
#define SCU_PINMUX_BOOT1 (P1_2) /* GPIO0[9] on P1_2 */
#define SCU_PINMUX_BOOT0 (P1_1) /* GPIO0[8] on P1_1 */
#define SCU_PINMUX_BOOT1 (P1_2) /* GPIO0[9] on P1_2 */
#ifndef HACKRF_ONE
#define SCU_PINMUX_BOOT2 (P2_8) /* GPIO5[7] on P2_8 */
#define SCU_PINMUX_BOOT3 (P2_9) /* GPIO1[10] on P2_9 */
#define SCU_PINMUX_BOOT2 (P2_8) /* GPIO5[7] on P2_8 */
#define SCU_PINMUX_BOOT3 (P2_9) /* GPIO1[10] on P2_9 */
#endif
#define SCU_PINMUX_PP_LCD_TE (P2_3) /* GPIO5[3] on P2_3 */
#define SCU_PINMUX_PP_LCD_RDX (P2_4) /* GPIO5[4] on P2_4 */
@ -89,147 +88,146 @@ extern "C"
/* USB peripheral */
#ifdef JAWBREAKER
#define SCU_PINMUX_USB_LED0 (P6_8)
#define SCU_PINMUX_USB_LED1 (P6_7)
#define SCU_PINMUX_USB_LED0 (P6_8)
#define SCU_PINMUX_USB_LED1 (P6_7)
#endif
/* SSP1 Peripheral PinMux */
#define SCU_SSP1_CIPO (P1_3) /* P1_3 */
#define SCU_SSP1_COPI (P1_4) /* P1_4 */
#define SCU_SSP1_SCK (P1_19) /* P1_19 */
#define SCU_SSP1_CS (P1_20) /* P1_20 */
#define SCU_SSP1_CIPO (P1_3) /* P1_3 */
#define SCU_SSP1_COPI (P1_4) /* P1_4 */
#define SCU_SSP1_SCK (P1_19) /* P1_19 */
#define SCU_SSP1_CS (P1_20) /* P1_20 */
/* CPLD JTAG interface */
#define SCU_PINMUX_CPLD_TDO (P9_5) /* GPIO5[18] */
#define SCU_PINMUX_CPLD_TCK (P6_1) /* GPIO3[ 0] */
#define SCU_PINMUX_CPLD_TDO (P9_5) /* GPIO5[18] */
#define SCU_PINMUX_CPLD_TCK (P6_1) /* GPIO3[ 0] */
#if (defined HACKRF_ONE || defined RAD1O)
#define SCU_PINMUX_CPLD_TMS (P6_5) /* GPIO3[ 4] */
#define SCU_PINMUX_CPLD_TDI (P6_2) /* GPIO3[ 1] */
#define SCU_PINMUX_CPLD_TMS (P6_5) /* GPIO3[ 4] */
#define SCU_PINMUX_CPLD_TDI (P6_2) /* GPIO3[ 1] */
#else
#define SCU_PINMUX_CPLD_TMS (P6_2) /* GPIO3[ 1] */
#define SCU_PINMUX_CPLD_TDI (P6_5) /* GPIO3[ 4] */
#define SCU_PINMUX_CPLD_TMS (P6_2) /* GPIO3[ 1] */
#define SCU_PINMUX_CPLD_TDI (P6_5) /* GPIO3[ 4] */
#endif
/* CPLD SGPIO interface */
#define SCU_PINMUX_SGPIO0 (P0_0)
#define SCU_PINMUX_SGPIO1 (P0_1)
#define SCU_PINMUX_SGPIO2 (P1_15)
#define SCU_PINMUX_SGPIO3 (P1_16)
#define SCU_PINMUX_SGPIO4 (P6_3)
#define SCU_PINMUX_SGPIO5 (P6_6)
#define SCU_PINMUX_SGPIO6 (P2_2)
#define SCU_PINMUX_SGPIO7 (P1_0)
#define SCU_PINMUX_SGPIO0 (P0_0)
#define SCU_PINMUX_SGPIO1 (P0_1)
#define SCU_PINMUX_SGPIO2 (P1_15)
#define SCU_PINMUX_SGPIO3 (P1_16)
#define SCU_PINMUX_SGPIO4 (P6_3)
#define SCU_PINMUX_SGPIO5 (P6_6)
#define SCU_PINMUX_SGPIO6 (P2_2)
#define SCU_PINMUX_SGPIO7 (P1_0)
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
#define SCU_PINMUX_SGPIO8 (P9_6)
#define SCU_PINMUX_SGPIO8 (P9_6)
#endif
#define SCU_PINMUX_SGPIO9 (P4_3)
#define SCU_PINMUX_SGPIO10 (P1_14)
#define SCU_PINMUX_SGPIO11 (P1_17)
#define SCU_PINMUX_SGPIO12 (P1_18)
#define SCU_PINMUX_SGPIO13 (P4_8)
#define SCU_PINMUX_SGPIO14 (P4_9)
#define SCU_PINMUX_SGPIO15 (P4_10)
#define SCU_PINMUX_SGPIO9 (P4_3)
#define SCU_PINMUX_SGPIO10 (P1_14)
#define SCU_PINMUX_SGPIO11 (P1_17)
#define SCU_PINMUX_SGPIO12 (P1_18)
#define SCU_PINMUX_SGPIO13 (P4_8)
#define SCU_PINMUX_SGPIO14 (P4_9)
#define SCU_PINMUX_SGPIO15 (P4_10)
/* MAX2837 GPIO (XCVR_CTL) PinMux */
#ifdef RAD1O
#define SCU_XCVR_RXHP (P8_1) /* GPIO[] on P8_1 */
#define SCU_XCVR_B6 (P8_2) /* GPIO[] on P8_2 */
#define SCU_XCVR_B7 (P9_3) /* GPIO[] on P8_3 */
#define SCU_XCVR_RXHP (P8_1) /* GPIO[] on P8_1 */
#define SCU_XCVR_B6 (P8_2) /* GPIO[] on P8_2 */
#define SCU_XCVR_B7 (P9_3) /* GPIO[] on P8_3 */
#endif
#define SCU_XCVR_ENABLE (P4_6) /* GPIO2[6] on P4_6 */
#define SCU_XCVR_RXENABLE (P4_5) /* GPIO2[5] on P4_5 */
#define SCU_XCVR_TXENABLE (P4_4) /* GPIO2[4] on P4_4 */
#define SCU_XCVR_CS (P1_20) /* GPIO0[15] on P1_20 */
#define SCU_XCVR_ENABLE (P4_6) /* GPIO2[6] on P4_6 */
#define SCU_XCVR_RXENABLE (P4_5) /* GPIO2[5] on P4_5 */
#define SCU_XCVR_TXENABLE (P4_4) /* GPIO2[4] on P4_4 */
#define SCU_XCVR_CS (P1_20) /* GPIO0[15] on P1_20 */
/* MAX5864 SPI chip select (AD_CS) GPIO PinMux */
#define SCU_AD_CS (P5_7) /* GPIO2[7] on P5_7 */
#define SCU_AD_CS (P5_7) /* GPIO2[7] on P5_7 */
/* RFFC5071 GPIO serial interface PinMux */
#if (defined JAWBREAKER || defined HACKRF_ONE)
#define SCU_MIXER_ENX (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_MIXER_SCLK (P2_6) /* GPIO5[6] on P2_6 */
#define SCU_MIXER_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */
#define SCU_MIXER_ENX (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_MIXER_SCLK (P2_6) /* GPIO5[6] on P2_6 */
#define SCU_MIXER_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_MIXER_RESETX (P5_5) /* GPIO2[14] on P5_5 */
#endif
#ifdef RAD1O
#define SCU_VCO_CE (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_VCO_SCLK (P2_6) /* GPIO5[6] on P2_6 */
#define SCU_VCO_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_VCO_LE (P5_5) /* GPIO2[14] on P5_5 */
#define SCU_VCO_MUX (PB_5) /* GPIO5[25] on PB_5 */
#define SCU_MIXER_EN (P6_8) /* GPIO5[16] on P6_8 */
#define SCU_SYNT_RFOUT_EN (P6_9) /* GPIO3[5] on P6_9 */
#define SCU_VCO_CE (P5_4) /* GPIO2[13] on P5_4 */
#define SCU_VCO_SCLK (P2_6) /* GPIO5[6] on P2_6 */
#define SCU_VCO_SDATA (P6_4) /* GPIO3[3] on P6_4 */
#define SCU_VCO_LE (P5_5) /* GPIO2[14] on P5_5 */
#define SCU_VCO_MUX (PB_5) /* GPIO5[25] on PB_5 */
#define SCU_MIXER_EN (P6_8) /* GPIO5[16] on P6_8 */
#define SCU_SYNT_RFOUT_EN (P6_9) /* GPIO3[5] on P6_9 */
#endif
/* RF LDO control */
#ifdef JAWBREAKER
#define SCU_RF_LDO_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#define SCU_RF_LDO_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
/* RF supply (VAA) control */
#ifdef HACKRF_ONE
#define SCU_NO_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#define SCU_NO_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
#ifdef RAD1O
#define SCU_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#define SCU_VAA_ENABLE (P5_0) /* GPIO2[9] on P5_0 */
#endif
/* SPI flash */
#define SCU_SSP0_CIPO (P3_6)
#define SCU_SSP0_COPI (P3_7)
#define SCU_SSP0_SCK (P3_3)
#define SCU_SSP0_CS (P3_8) /* GPIO5[11] on P3_8 */
#define SCU_FLASH_HOLD (P3_4) /* GPIO1[14] on P3_4 */
#define SCU_FLASH_WP (P3_5) /* GPIO1[15] on P3_5 */
#define SCU_SSP0_CIPO (P3_6)
#define SCU_SSP0_COPI (P3_7)
#define SCU_SSP0_SCK (P3_3)
#define SCU_SSP0_CS (P3_8) /* GPIO5[11] on P3_8 */
#define SCU_FLASH_HOLD (P3_4) /* GPIO1[14] on P3_4 */
#define SCU_FLASH_WP (P3_5) /* GPIO1[15] on P3_5 */
/* RF switch control */
#ifdef HACKRF_ONE
#define SCU_HP (P4_0) /* GPIO2[0] on P4_0 */
#define SCU_LP (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_TX_MIX_BP (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_NO_MIX_BYPASS (P1_7) /* GPIO1[0] on P1_7 */
#define SCU_RX_MIX_BP (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */
#define SCU_TX (P6_7) /* GPIO5[15] on P6_7 */
#define SCU_MIX_BYPASS (P6_8) /* GPIO5[16] on P6_8 */
#define SCU_RX (P2_5) /* GPIO5[5] on P2_5 */
#define SCU_NO_TX_AMP_PWR (P6_9) /* GPIO3[5] on P6_9 */
#define SCU_AMP_BYPASS (P2_10) /* GPIO0[14] on P2_10 */
#define SCU_RX_AMP (P2_11) /* GPIO1[11] on P2_11 */
#define SCU_NO_RX_AMP_PWR (P2_12) /* GPIO1[12] on P2_12 */
#define SCU_HP (P4_0) /* GPIO2[0] on P4_0 */
#define SCU_LP (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_TX_MIX_BP (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_NO_MIX_BYPASS (P1_7) /* GPIO1[0] on P1_7 */
#define SCU_RX_MIX_BP (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */
#define SCU_TX (P6_7) /* GPIO5[15] on P6_7 */
#define SCU_MIX_BYPASS (P6_8) /* GPIO5[16] on P6_8 */
#define SCU_RX (P2_5) /* GPIO5[5] on P2_5 */
#define SCU_NO_TX_AMP_PWR (P6_9) /* GPIO3[5] on P6_9 */
#define SCU_AMP_BYPASS (P2_10) /* GPIO0[14] on P2_10 */
#define SCU_RX_AMP (P2_11) /* GPIO1[11] on P2_11 */
#define SCU_NO_RX_AMP_PWR (P2_12) /* GPIO1[12] on P2_12 */
#endif
#ifdef RAD1O
#define SCU_BY_AMP (P1_7) /* GPIO1[0] on P1_7 */
#define SCU_BY_AMP_N (P2_5) /* GPIO5[5] on P2_5 */
#define SCU_TX_RX (P2_10) /* GPIO0[14] on P2_10 */
#define SCU_TX_RX_N (P2_11) /* GPIO1[11] on P2_11 */
#define SCU_BY_MIX (P2_12) /* GPIO1[12] on P2_12 */
#define SCU_BY_MIX_N (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_LOW_HIGH_FILT (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_LOW_HIGH_FILT_N (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */
#define SCU_RX_LNA (P6_7) /* GPIO5[15] on P6_7 */
#define SCU_BY_AMP (P1_7) /* GPIO1[0] on P1_7 */
#define SCU_BY_AMP_N (P2_5) /* GPIO5[5] on P2_5 */
#define SCU_TX_RX (P2_10) /* GPIO0[14] on P2_10 */
#define SCU_TX_RX_N (P2_11) /* GPIO1[11] on P2_11 */
#define SCU_BY_MIX (P2_12) /* GPIO1[12] on P2_12 */
#define SCU_BY_MIX_N (P5_1) /* GPIO2[10] on P5_1 */
#define SCU_LOW_HIGH_FILT (P5_2) /* GPIO2[11] on P5_2 */
#define SCU_LOW_HIGH_FILT_N (P5_3) /* GPIO2[12] on P5_3 */
#define SCU_TX_AMP (P5_6) /* GPIO2[15] on P5_6 */
#define SCU_RX_LNA (P6_7) /* GPIO5[15] on P6_7 */
#endif
#define SCU_PINMUX_PP_D0 (P7_0) /* GPIO3[8] */
#define SCU_PINMUX_PP_D1 (P7_1) /* GPIO3[9] */
#define SCU_PINMUX_PP_D2 (P7_2) /* GPIO3[10] */
#define SCU_PINMUX_PP_D3 (P7_3) /* GPIO3[11] */
#define SCU_PINMUX_PP_D4 (P7_4) /* GPIO3[12] */
#define SCU_PINMUX_PP_D5 (P7_5) /* GPIO3[13] */
#define SCU_PINMUX_PP_D6 (P7_6) /* GPIO3[14] */
#define SCU_PINMUX_PP_D7 (P7_7) /* GPIO3[15] */
#define SCU_PINMUX_PP_D0 (P7_0) /* GPIO3[8] */
#define SCU_PINMUX_PP_D1 (P7_1) /* GPIO3[9] */
#define SCU_PINMUX_PP_D2 (P7_2) /* GPIO3[10] */
#define SCU_PINMUX_PP_D3 (P7_3) /* GPIO3[11] */
#define SCU_PINMUX_PP_D4 (P7_4) /* GPIO3[12] */
#define SCU_PINMUX_PP_D5 (P7_5) /* GPIO3[13] */
#define SCU_PINMUX_PP_D6 (P7_6) /* GPIO3[14] */
#define SCU_PINMUX_PP_D7 (P7_7) /* GPIO3[15] */
/* TODO add other Pins */
#define SCU_PINMUX_GPIO3_8 (P7_0) /* GPIO3[8] */
#define SCU_PINMUX_GPIO3_9 (P7_1) /* GPIO3[9] */
#define SCU_PINMUX_GPIO3_10 (P7_2) /* GPIO3[10] */
#define SCU_PINMUX_GPIO3_11 (P7_3) /* GPIO3[11] */
#define SCU_PINMUX_GPIO3_12 (P7_4) /* GPIO3[12] */
#define SCU_PINMUX_GPIO3_13 (P7_5) /* GPIO3[13] */
#define SCU_PINMUX_GPIO3_14 (P7_6) /* GPIO3[14] */
#define SCU_PINMUX_GPIO3_15 (P7_7) /* GPIO3[15] */
#define SCU_PINMUX_GPIO3_8 (P7_0) /* GPIO3[8] */
#define SCU_PINMUX_GPIO3_9 (P7_1) /* GPIO3[9] */
#define SCU_PINMUX_GPIO3_10 (P7_2) /* GPIO3[10] */
#define SCU_PINMUX_GPIO3_11 (P7_3) /* GPIO3[11] */
#define SCU_PINMUX_GPIO3_12 (P7_4) /* GPIO3[12] */
#define SCU_PINMUX_GPIO3_13 (P7_5) /* GPIO3[13] */
#define SCU_PINMUX_GPIO3_14 (P7_6) /* GPIO3[14] */
#define SCU_PINMUX_GPIO3_15 (P7_7) /* GPIO3[15] */
#define SCU_PINMUX_PP_TDO (P1_5) /* GPIO1[8] */
#define SCU_PINMUX_SD_POW (P1_5) /* GPIO1[8] */
@ -242,14 +240,14 @@ extern "C"
#define SCU_PINMUX_SD_DAT3 (P1_12) /* GPIO1[5] */
#define SCU_PINMUX_SD_CD (P1_13) /* GPIO1[6] */
#define SCU_PINMUX_PP_IO_STBX (P2_0) /* GPIO5[0] */
#define SCU_PINMUX_PP_ADDR (P2_1) /* GPIO5[1] */
#define SCU_PINMUX_U0_TXD (P2_0) /* GPIO5[0] */
#define SCU_PINMUX_U0_RXD (P2_1) /* GPIO5[1] */
#define SCU_PINMUX_PP_IO_STBX (P2_0) /* GPIO5[0] */
#define SCU_PINMUX_PP_ADDR (P2_1) /* GPIO5[1] */
#define SCU_PINMUX_U0_TXD (P2_0) /* GPIO5[0] */
#define SCU_PINMUX_U0_RXD (P2_1) /* GPIO5[1] */
#define SCU_PINMUX_ISP (P2_7) /* GPIO0[7] */
#define SCU_PINMUX_ISP (P2_7) /* GPIO0[7] */
#define SCU_PINMUX_GP_CLKIN (P4_7)
#define SCU_PINMUX_GP_CLKIN (P4_7)
typedef enum {
TRANSCEIVER_MODE_OFF = 0,

View File

@ -26,9 +26,10 @@
#include <stddef.h>
#define UNUSED(x) (void)(x)
#define UNUSED(x) (void) (x)
/* Stub functions for null UI function table */
// clang-format off
void hackrf_ui_init_null(void) { }
void hackrf_ui_deinit_null(void) { }
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); }
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
* need to check for null UI before calling a function in the table.
*/
@ -65,34 +68,35 @@ static const hackrf_ui_t hackrf_ui_null = {
&hackrf_ui_set_antenna_bias_null,
&hackrf_ui_set_clock_source_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 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. */
if( ui == NULL && ui_enabled ) {
if (ui == NULL && ui_enabled) {
#ifdef HACKRF_ONE
if( portapack_hackrf_ui_init ) {
if (portapack_hackrf_ui_init) {
ui = portapack_hackrf_ui_init();
}
#endif
#ifdef RAD1O
if( rad1o_ui_setup ) {
if (rad1o_ui_setup) {
ui = rad1o_ui_setup();
}
#endif
}
if( ui == NULL ) {
if (ui == NULL) {
ui = &hackrf_ui_null;
}
return ui;
}
void hackrf_ui_set_enable(bool enabled) {
void hackrf_ui_set_enable(bool enabled)
{
if (ui_enabled != enabled) {
ui_enabled = enabled;
hackrf_ui()->deinit();

View File

@ -21,19 +21,23 @@
#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);
}
void i2c_bus_stop(i2c_bus_t* const bus) {
void i2c_bus_stop(i2c_bus_t* const bus)
{
bus->stop(bus);
}
void i2c_bus_transfer(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address,
const uint8_t* const tx, const size_t tx_count,
uint8_t* const rx, const size_t rx_count
) {
const uint8_t* const tx,
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);
}

View File

@ -35,9 +35,10 @@ struct i2c_bus_t {
void (*transfer)(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address,
const uint8_t* const tx, const size_t tx_count,
uint8_t* const rx, const size_t rx_count
);
const uint8_t* const tx,
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);
@ -45,8 +46,9 @@ void i2c_bus_stop(i2c_bus_t* const bus);
void i2c_bus_transfer(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address,
const uint8_t* const tx, const size_t tx_count,
uint8_t* const rx, const size_t rx_count
);
const uint8_t* const tx,
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,30 +26,35 @@
/* 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 uint32_t port = (uint32_t)bus->obj;
const uint32_t port = (uint32_t) bus->obj;
i2c_init(port, config->duty_cycle_count);
}
void i2c_lpc_stop(i2c_bus_t* const bus) {
const uint32_t port = (uint32_t)bus->obj;
void i2c_lpc_stop(i2c_bus_t* const bus)
{
const uint32_t port = (uint32_t) bus->obj;
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 uint8_t* const data_tx, const size_t count_tx,
uint8_t* const data_rx, const size_t count_rx
) {
const uint32_t port = (uint32_t)bus->obj;
const uint8_t* const data_tx,
const size_t count_tx,
uint8_t* const data_rx,
const size_t count_rx)
{
const uint32_t port = (uint32_t) bus->obj;
size_t i;
bool ack = false;
if (data_tx && (count_tx > 0)) {
i2c_tx_start(port);
i2c_tx_byte(port, (peripheral_address << 1) | I2C_WRITE);
for(i=0; i<count_tx; i++) {
for (i = 0; i < count_tx; i++) {
i2c_tx_byte(port, data_tx[i]);
}
}
@ -57,9 +62,9 @@ void i2c_lpc_transfer(i2c_bus_t* const bus,
if (data_rx && (count_rx > 0)) {
i2c_tx_start(port);
i2c_tx_byte(port, (peripheral_address << 1) | I2C_READ);
for(i=0; i<count_rx; i++) {
for (i = 0; i < count_rx; i++) {
/* ACK each byte except the last */
ack = (i!=count_rx-1);
ack = (i != count_rx - 1);
data_rx[i] = i2c_rx_byte(port, ack);
}
}
@ -67,8 +72,9 @@ void i2c_lpc_transfer(i2c_bus_t* const bus,
i2c_stop(port);
}
bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address) {
const uint32_t port = (uint32_t)bus->obj;
bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address)
{
const uint32_t port = (uint32_t) bus->obj;
i2c_tx_start(port);
i2c_tx_byte(port, (device_address << 1) | I2C_WRITE);

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_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 uint8_t* const data_tx, const size_t count_tx,
uint8_t* const data_rx, const size_t count_rx
);
const uint8_t* const data_tx,
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);
#endif/*__I2C_LPC_H__*/
#endif /*__I2C_LPC_H__*/

View File

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

View File

@ -34,44 +34,44 @@
#include "max2837_regs.def" // private register def macros
/* Default register values. */
static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
0x150, /* 0 */
0x002, /* 1 */
0x1f4, /* 2 */
0x1b9, /* 3 */
0x00a, /* 4 */
0x080, /* 5 */
0x006, /* 6 */
0x000, /* 7 */
0x080, /* 8 */
0x018, /* 9 */
0x058, /* 10 */
0x016, /* 11 */
0x24f, /* 12 */
0x150, /* 13 */
0x1c5, /* 14 */
0x081, /* 15 */
0x01c, /* 16 */
0x155, /* 17 */
0x155, /* 18 */
0x153, /* 19 */
0x241, /* 20 */
static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
0x150, /* 0 */
0x002, /* 1 */
0x1f4, /* 2 */
0x1b9, /* 3 */
0x00a, /* 4 */
0x080, /* 5 */
0x006, /* 6 */
0x000, /* 7 */
0x080, /* 8 */
0x018, /* 9 */
0x058, /* 10 */
0x016, /* 11 */
0x24f, /* 12 */
0x150, /* 13 */
0x1c5, /* 14 */
0x081, /* 15 */
0x01c, /* 16 */
0x155, /* 17 */
0x155, /* 18 */
0x153, /* 19 */
0x241, /* 20 */
/*
* Charge Pump Common Mode Enable bit (0) of register 21 must be set or TX
* does not work. Page 1 of the SPI doc says not to set it (0x02c), but
* page 21 says it should be set by default (0x02d).
*/
0x02d, /* 21 */
0x1a9, /* 22 */
0x24f, /* 23 */
0x180, /* 24 */
0x100, /* 25 */
0x3ca, /* 26 */
0x3e3, /* 27 */
0x0c0, /* 28 */
0x3f0, /* 29 */
0x080, /* 30 */
0x000 }; /* 31 */
0x02d, /* 21 */
0x1a9, /* 22 */
0x24f, /* 23 */
0x180, /* 24 */
0x100, /* 25 */
0x3ca, /* 26 */
0x3e3, /* 27 */
0x0c0, /* 28 */
0x3f0, /* 29 */
0x080, /* 30 */
0x000}; /* 31 */
/* Set up all registers according to defaults specified in docs. */
static void max2837_init(max2837_driver_t* const drv)
@ -93,7 +93,7 @@ static void max2837_init(max2837_driver_t* const drv)
void max2837_setup(max2837_driver_t* const drv)
{
max2837_init(drv);
/* Use SPI control instead of B1-B7 pins for gain settings. */
set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1);
set_MAX2837_TXVGA_GAIN_MSB_SPI_EN(drv, 1);
@ -119,13 +119,15 @@ void max2837_setup(max2837_driver_t* const 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);
spi_bus_transfer(drv->bus, &value, 1);
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);
spi_bus_transfer(drv->bus, &value, 1);
}
@ -153,18 +155,20 @@ static inline void max2837_reg_commit(max2837_driver_t* const drv, uint8_t r)
void max2837_regs_commit(max2837_driver_t* const drv)
{
int r;
for(r = 0; r < MAX2837_NUM_REGS; r++) {
for (r = 0; r < MAX2837_NUM_REGS; r++) {
if ((drv->regs_dirty >> r) & 0x1) {
max2837_reg_commit(drv, r);
}
}
}
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);
}
max2837_mode_t max2837_mode(max2837_driver_t* const drv) {
max2837_mode_t max2837_mode(max2837_driver_t* const drv)
{
return drv->mode;
}
@ -210,16 +214,13 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq)
if (freq < 2400000000U) {
band = MAX2837_LOGEN_BSW_2_3;
lna_band = MAX2837_LNAband_2_4;
}
else if (freq < 2500000000U) {
} else if (freq < 2500000000U) {
band = MAX2837_LOGEN_BSW_2_4;
lna_band = MAX2837_LNAband_2_4;
}
else if (freq < 2600000000U) {
} else if (freq < 2600000000U) {
band = MAX2837_LOGEN_BSW_2_5;
lna_band = MAX2837_LNAband_2_6;
}
else {
} else {
band = MAX2837_LOGEN_BSW_2_6;
lna_band = MAX2837_LNAband_2_6;
}
@ -229,7 +230,7 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq)
div_rem = freq % 30000000;
div_frac = 0;
div_cmp = 30000000;
for( i = 0; i < 20; i++) {
for (i = 0; i < 20; i++) {
div_frac <<= 1;
div_cmp >>= 1;
if (div_rem > div_cmp) {
@ -259,6 +260,7 @@ typedef struct {
uint32_t ft;
} max2837_ft_t;
// clang-format off
static const max2837_ft_t max2837_ft[] = {
{ 1750000, MAX2837_FT_1_75M },
{ 2500000, MAX2837_FT_2_5M },
@ -278,6 +280,7 @@ static const max2837_ft_t max2837_ft[] = {
{ 28000000, MAX2837_FT_28M },
{ 0, 0 },
};
//clang-format on
uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz) {
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) {
if( (gain_db & 0x1) || gain_db > 62)/* 0b11111*2 */
if( (gain_db & 0x1) || gain_db > 62) {/* 0b11111*2 */
return false;
}
set_MAX2837_VGA(drv, 31-(gain_db >> 1) );
max2837_reg_commit(drv, 5);

View File

@ -30,7 +30,7 @@
#include "spi_bus.h"
/* 32 registers, each containing 10 bits of data. */
#define MAX2837_NUM_REGS 32
#define MAX2837_NUM_REGS 32
#define MAX2837_DATA_REGS_MAX_VALUE 1024
typedef enum {
@ -81,11 +81,13 @@ extern void max2837_stop(max2837_driver_t* const drv);
/* Set frequency in Hz. Frequency setting is a multi-step function
* where order of register writes matters. */
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_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);
extern void max2837_tx(max2837_driver_t* const drv);
extern void max2837_rx(max2837_driver_t* const drv);

View File

@ -25,11 +25,12 @@
#include <libopencm3/lpc43xx/scu.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) */
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_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
scu_pinmux(SCU_XCVR_CS, SCU_GPIO_FAST);
@ -44,7 +45,8 @@ void max2837_target_init(max2837_driver_t* const drv) {
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:
* All circuit blocks are powered down, except the 4-wire serial bus
* and its internal programmable registers.

View File

@ -2,13 +2,13 @@
#include "max2871_regs.h"
#if (defined DEBUG)
#include <stdio.h>
#define LOG printf
#include <stdio.h>
#define LOG printf
#else
#define LOG(x,...)
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h"
#define LOG(x, ...)
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h"
#endif
#include <stdint.h>
@ -43,12 +43,12 @@ void max2871_setup(max2871_driver_t* const drv)
gpio_set(drv->gpio_vco_ce); /* active high */
gpio_clear(drv->gpio_vco_sclk);
gpio_clear(drv->gpio_vco_sdata);
gpio_set(drv->gpio_vco_le); /* active low */
gpio_set(drv->gpio_vco_le); /* active low */
gpio_set(drv->gpio_synt_rfout_en); /* active high */
max2871_regs_init();
int i;
for(i = 5; i >= 0; i--) {
for (i = 5; i >= 0; i--) {
max2871_spi_write(drv, i, max2871_get_register(i));
delay_ms(20);
}
@ -62,7 +62,7 @@ void max2871_setup(max2871_driver_t* const drv)
max2871_set_M(0);
max2871_set_LDS(0);
max2871_set_SDN(0);
max2871_set_MUX(0x0C); /* Register 6 readback */
max2871_set_MUX(0x0C); /* Register 6 readback */
max2871_set_DBR(0);
max2871_set_RDIV2(0);
max2871_set_R(1); /* 40 MHz f_PFD */
@ -84,8 +84,8 @@ void max2871_setup(max2871_driver_t* const drv)
max2871_set_SDLDO(0);
max2871_set_SDDIV(0);
max2871_set_SDREF(0);
max2871_set_BS(20*40); /* For 40 MHz f_PFD */
max2871_set_FB(1); /* Do not put DIVA into the feedback loop */
max2871_set_BS(20 * 40); /* For 40 MHz f_PFD */
max2871_set_FB(1); /* Do not put DIVA into the feedback loop */
max2871_set_DIVA(0);
max2871_set_SDVCO(0);
max2871_set_MTLD(1);
@ -108,14 +108,13 @@ void max2871_setup(max2871_driver_t* const drv)
static void delay_ms(int ms)
{
uint32_t i;
while(ms--) {
while (ms--) {
for (i = 0; i < 20000; i++) {
__asm__("nop");
}
}
}
static void serial_delay(void)
{
uint32_t i;
@ -124,19 +123,19 @@ static void serial_delay(void)
__asm__("nop");
}
/* SPI register write
*
* Send 32 bits:
* First 29 bits are data
* 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
LOG("0x%04x -> reg%d\n", v, r);
#else
uint32_t bits = 32;
uint32_t msb = 1 << (bits -1);
uint32_t msb = 1 << (bits - 1);
uint32_t data = v | r;
/* make sure everything is starting in the correct state */
@ -194,7 +193,7 @@ static uint32_t max2871_spi_read(max2871_driver_t* const drv)
static void max2871_write_registers(max2871_driver_t* const drv)
{
int i;
for(i = 5; i >= 0; i--) {
for (i = 5; i >= 0; i--) {
max2871_spi_write(drv, i, max2871_get_register(i));
}
}
@ -205,7 +204,7 @@ uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz)
int n = mhz / 40;
int diva = 0;
while(n * 40 < 3000) {
while (n * 40 < 3000) {
n *= 2;
diva += 1;
}
@ -217,20 +216,20 @@ uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz)
max2871_set_DIVA(diva);
max2871_write_registers(drv);
while(max2871_spi_read(drv) & MAX2871_VASA);
while (max2871_spi_read(drv) & MAX2871_VASA) {}
max2871_set_RFA_EN(1);
max2871_write_registers(drv);
return (mhz/40)*40 * 1000000;
return (mhz / 40) * 40 * 1000000;
}
void max2871_enable(max2871_driver_t* const drv)
{
gpio_set(drv->gpio_vco_ce);
}
void max2871_disable(max2871_driver_t* const drv)
{
gpio_clear(drv->gpio_vco_ce);
}

View File

@ -5,295 +5,295 @@ static uint32_t registers[6];
void max2871_regs_init(void)
{
registers[0] = 0x007D0000;
registers[1] = 0x2000FFF9;
registers[2] = 0x00004042;
registers[3] = 0x0000000B;
registers[4] = 0x6180B23C;
registers[5] = 0x00400005;
registers[0] = 0x007D0000;
registers[1] = 0x2000FFF9;
registers[2] = 0x00004042;
registers[3] = 0x0000000B;
registers[4] = 0x6180B23C;
registers[5] = 0x00400005;
}
uint32_t max2871_get_register(int reg)
{
return registers[reg];
return registers[reg];
}
void max2871_set_INT(uint32_t v)
{
registers[0] &= ~(0x1 << 31);
registers[0] |= v << 31;
registers[0] &= ~(0x1 << 31);
registers[0] |= v << 31;
}
void max2871_set_N(uint32_t v)
{
registers[0] &= ~(0xFFFF << 15);
registers[0] |= v << 15;
registers[0] &= ~(0xFFFF << 15);
registers[0] |= v << 15;
}
void max2871_set_FRAC(uint32_t v)
{
registers[0] &= ~(0xFFF << 3);
registers[0] |= v << 3;
registers[0] &= ~(0xFFF << 3);
registers[0] |= v << 3;
}
void max2871_set_CPL(uint32_t v)
{
registers[1] &= ~(0x3 << 29);
registers[1] |= v << 29;
registers[1] &= ~(0x3 << 29);
registers[1] |= v << 29;
}
void max2871_set_CPT(uint32_t v)
{
registers[1] &= ~(0x3 << 27);
registers[1] |= v << 27;
registers[1] &= ~(0x3 << 27);
registers[1] |= v << 27;
}
void max2871_set_P(uint32_t v)
{
registers[1] &= ~(0xFFF << 15);
registers[1] |= v << 15;
registers[1] &= ~(0xFFF << 15);
registers[1] |= v << 15;
}
void max2871_set_M(uint32_t v)
{
registers[1] &= ~(0xFFF << 3);
registers[1] |= v << 3;
registers[1] &= ~(0xFFF << 3);
registers[1] |= v << 3;
}
void max2871_set_LDS(uint32_t v)
{
registers[2] &= ~(0x1 << 31);
registers[2] |= v << 31;
registers[2] &= ~(0x1 << 31);
registers[2] |= v << 31;
}
void max2871_set_SDN(uint32_t v)
{
registers[2] &= ~(0x3 << 29);
registers[2] |= v << 29;
registers[2] &= ~(0x3 << 29);
registers[2] |= v << 29;
}
void max2871_set_MUX(uint32_t v)
{
registers[2] &= ~(0x7 << 26);
registers[5] &= ~(0x1 << 18);
registers[2] |= (v & 0x7) << 26;
registers[5] |= ((v & 0x8) >> 3) << 18;
registers[2] &= ~(0x7 << 26);
registers[5] &= ~(0x1 << 18);
registers[2] |= (v & 0x7) << 26;
registers[5] |= ((v & 0x8) >> 3) << 18;
}
void max2871_set_DBR(uint32_t v)
{
registers[2] &= ~(0x1 << 25);
registers[2] |= v << 25;
registers[2] &= ~(0x1 << 25);
registers[2] |= v << 25;
}
void max2871_set_RDIV2(uint32_t v)
{
registers[2] &= ~(0x1 << 24);
registers[2] |= v << 24;
registers[2] &= ~(0x1 << 24);
registers[2] |= v << 24;
}
void max2871_set_R(uint32_t v)
{
registers[2] &= ~(0x3FF << 14);
registers[2] |= v << 14;
registers[2] &= ~(0x3FF << 14);
registers[2] |= v << 14;
}
void max2871_set_REG4DB(uint32_t v)
{
registers[2] &= ~(0x1 << 13);
registers[2] |= v << 13;
registers[2] &= ~(0x1 << 13);
registers[2] |= v << 13;
}
void max2871_set_CP(uint32_t v)
{
registers[2] &= ~(0xF << 9);
registers[2] |= v << 9;
registers[2] &= ~(0xF << 9);
registers[2] |= v << 9;
}
void max2871_set_LDF(uint32_t v)
{
registers[2] &= ~(0x1 << 8);
registers[2] |= v << 8;
registers[2] &= ~(0x1 << 8);
registers[2] |= v << 8;
}
void max2871_set_LDP(uint32_t v)
{
registers[2] &= ~(0x1 << 7);
registers[2] |= v << 7;
registers[2] &= ~(0x1 << 7);
registers[2] |= v << 7;
}
void max2871_set_PDP(uint32_t v)
{
registers[2] &= ~(0x1 << 6);
registers[2] |= v << 6;
registers[2] &= ~(0x1 << 6);
registers[2] |= v << 6;
}
void max2871_set_SHDN(uint32_t v)
{
registers[2] &= ~(0x1 << 5);
registers[2] |= v << 5;
registers[2] &= ~(0x1 << 5);
registers[2] |= v << 5;
}
void max2871_set_TRI(uint32_t v)
{
registers[2] &= ~(0x1 << 4);
registers[2] |= v << 4;
registers[2] &= ~(0x1 << 4);
registers[2] |= v << 4;
}
void max2871_set_RST(uint32_t v)
{
registers[2] &= ~(0x1 << 3);
registers[2] |= v << 3;
registers[2] &= ~(0x1 << 3);
registers[2] |= v << 3;
}
void max2871_set_VCO(uint32_t v)
{
registers[3] &= ~(0x3F << 26);
registers[3] |= v << 26;
registers[3] &= ~(0x3F << 26);
registers[3] |= v << 26;
}
void max2871_set_VAS_SHDN(uint32_t v)
{
registers[3] &= ~(0x1 << 25);
registers[3] |= v << 25;
registers[3] &= ~(0x1 << 25);
registers[3] |= v << 25;
}
void max2871_set_VAS_TEMP(uint32_t v)
{
registers[3] &= ~(0x1 << 24);
registers[3] |= v << 24;
registers[3] &= ~(0x1 << 24);
registers[3] |= v << 24;
}
void max2871_set_CSM(uint32_t v)
{
registers[3] &= ~(0x1 << 18);
registers[3] |= v << 18;
registers[3] &= ~(0x1 << 18);
registers[3] |= v << 18;
}
void max2871_set_MUTEDEL(uint32_t v)
{
registers[3] &= ~(0x1 << 17);
registers[3] |= v << 17;
registers[3] &= ~(0x1 << 17);
registers[3] |= v << 17;
}
void max2871_set_CDM(uint32_t v)
{
registers[3] &= ~(0x3 << 15);
registers[3] |= v << 15;
registers[3] &= ~(0x3 << 15);
registers[3] |= v << 15;
}
void max2871_set_CDIV(uint32_t v)
{
registers[3] &= ~(0xFFF << 3);
registers[3] |= v << 3;
registers[3] &= ~(0xFFF << 3);
registers[3] |= v << 3;
}
void max2871_set_SDLDO(uint32_t v)
{
registers[4] &= ~(0x1 << 28);
registers[4] |= v << 28;
registers[4] &= ~(0x1 << 28);
registers[4] |= v << 28;
}
void max2871_set_SDDIV(uint32_t v)
{
registers[4] &= ~(0x1 << 27);
registers[4] |= v << 27;
registers[4] &= ~(0x1 << 27);
registers[4] |= v << 27;
}
void max2871_set_SDREF(uint32_t v)
{
registers[4] &= ~(0x1 << 26);
registers[4] |= v << 26;
registers[4] &= ~(0x1 << 26);
registers[4] |= v << 26;
}
void max2871_set_BS(uint32_t v)
{
registers[4] &= ~(0x3 << 24);
registers[4] &= ~(0xFF << 12);
registers[4] |= ((v & 0x300) >> 8) << 24;
registers[4] |= (v & 0xFF) << 12;
registers[4] &= ~(0x3 << 24);
registers[4] &= ~(0xFF << 12);
registers[4] |= ((v & 0x300) >> 8) << 24;
registers[4] |= (v & 0xFF) << 12;
}
void max2871_set_FB(uint32_t v)
{
registers[4] &= ~(0x1 << 23);
registers[4] |= v << 23;
registers[4] &= ~(0x1 << 23);
registers[4] |= v << 23;
}
void max2871_set_DIVA(uint32_t v)
{
registers[4] &= ~(0x7 << 20);
registers[4] |= v << 20;
registers[4] &= ~(0x7 << 20);
registers[4] |= v << 20;
}
void max2871_set_SDVCO(uint32_t v)
{
registers[4] &= ~(0x1 << 11);
registers[4] |= v << 11;
registers[4] &= ~(0x1 << 11);
registers[4] |= v << 11;
}
void max2871_set_MTLD(uint32_t v)
{
registers[4] &= ~(0x1 << 10);
registers[4] |= v << 10;
registers[4] &= ~(0x1 << 10);
registers[4] |= v << 10;
}
void max2871_set_BDIV(uint32_t v)
{
registers[4] &= ~(0x1 << 9);
registers[4] |= v << 9;
registers[4] &= ~(0x1 << 9);
registers[4] |= v << 9;
}
void max2871_set_RFB_EN(uint32_t v)
{
registers[4] &= ~(0x1 << 8);
registers[4] |= v << 8;
registers[4] &= ~(0x1 << 8);
registers[4] |= v << 8;
}
void max2871_set_BPWR(uint32_t v)
{
registers[4] &= ~(0x3 << 6);
registers[4] |= v << 6;
registers[4] &= ~(0x3 << 6);
registers[4] |= v << 6;
}
void max2871_set_RFA_EN(uint32_t v)
{
registers[4] &= ~(0x1 << 5);
registers[4] |= v << 5;
registers[4] &= ~(0x1 << 5);
registers[4] |= v << 5;
}
void max2871_set_APWR(uint32_t v)
{
registers[4] &= ~(0x3 << 3);
registers[4] |= v << 3;
registers[4] &= ~(0x3 << 3);
registers[4] |= v << 3;
}
void max2871_set_SDPLL(uint32_t v)
{
registers[5] &= ~(0x1 << 25);
registers[5] |= v << 25;
registers[5] &= ~(0x1 << 25);
registers[5] |= v << 25;
}
void max2871_set_F01(uint32_t v)
{
registers[5] &= ~(0x1 << 24);
registers[5] |= v << 24;
registers[5] &= ~(0x1 << 24);
registers[5] |= v << 24;
}
void max2871_set_LD(uint32_t v)
{
registers[5] &= ~(0x3 << 22);
registers[5] |= v << 22;
registers[5] &= ~(0x3 << 22);
registers[5] |= v << 22;
}
void max2871_set_ADCS(uint32_t v)
{
registers[5] &= ~(0x1 << 6);
registers[5] |= v << 6;
registers[5] &= ~(0x1 << 6);
registers[5] |= v << 6;
}
void max2871_set_ADCM(uint32_t v)
{
registers[5] &= ~(0x7 << 3);
registers[5] |= v << 3;
registers[5] &= ~(0x7 << 3);
registers[5] |= v << 3;
}

View File

@ -2,7 +2,7 @@
#define MAX2871_REGS_H
#include <stdint.h>
#define MAX2871_VASA (1 << 9)
#define MAX2871_VASA (1 << 9)
void max2871_regs_init(void);
uint32_t max2871_get_register(int reg);

View File

@ -23,15 +23,18 @@
#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);
}
static void max5864_init(max5864_driver_t* const drv) {
static void max5864_init(max5864_driver_t* const drv)
{
drv->target_init(drv);
}
void max5864_setup(max5864_driver_t* const drv) {
void max5864_setup(max5864_driver_t* const drv)
{
max5864_init(drv);
}

View File

@ -24,13 +24,14 @@
#include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h"
void max5864_target_init(max5864_driver_t* const drv) {
(void)drv;
void max5864_target_init(max5864_driver_t* const drv)
{
(void) drv;
/* 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_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
scu_pinmux(SCU_SSP1_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION1));
/*
* Configure CS_AD pin to keep the MAX5864 SPI disabled while we use the

View File

@ -26,4 +26,4 @@
void max5864_target_init(max5864_driver_t* const drv);
#endif/*__MAX5864_TARGET_H__*/
#endif /*__MAX5864_TARGET_H__*/

View File

@ -5,20 +5,22 @@
#include "gpio_lpc.h"
/* RFFC5071 GPIO serial interface PinMux */
// clang-format off
#if (defined JAWBREAKER || defined HACKRF_ONE)
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_data = GPIO(3, 3);
static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
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_data = GPIO(3, 3);
static struct gpio_t gpio_rffc5072_reset = GPIO(2, 14);
#endif
#ifdef RAD1O
static struct gpio_t gpio_vco_ce = GPIO(2, 13);
static struct gpio_t gpio_vco_sclk = GPIO(5, 6);
static struct gpio_t gpio_vco_sdata = GPIO(3, 3);
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_synt_rfout_en = GPIO(3, 5);
static struct gpio_t gpio_vco_ce = GPIO(2, 13);
static struct gpio_t gpio_vco_sclk = GPIO(5, 6);
static struct gpio_t gpio_vco_sdata = GPIO(3, 3);
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_synt_rfout_en = GPIO(3, 5);
#endif
// clang-format on
#if (defined JAWBREAKER || defined HACKRF_ONE)
const rffc5071_spi_config_t rffc5071_spi_config = {

View File

@ -24,12 +24,12 @@
#define __MIXER_H
#if (defined JAWBREAKER || defined HACKRF_ONE)
#include "rffc5071.h"
#include "rffc5071.h"
typedef rffc5071_driver_t mixer_driver_t;
#endif
#ifdef RAD1O
#include "max2871.h"
#include "max2871.h"
typedef max2871_driver_t mixer_driver_t;
#endif

View File

@ -30,14 +30,14 @@
/*
* I2C Mode
*/
#define OPERACAKE_PIN_OE(x) (x<<7)
#define OPERACAKE_PIN_U2CTRL1(x) (x<<6)
#define OPERACAKE_PIN_U2CTRL0(x) (x<<5)
#define OPERACAKE_PIN_U3CTRL1(x) (x<<4)
#define OPERACAKE_PIN_U3CTRL0(x) (x<<3)
#define OPERACAKE_PIN_U1CTRL(x) (x<<2)
#define OPERACAKE_PIN_LEDEN2(x) (x<<1)
#define OPERACAKE_PIN_LEDEN(x) (x<<0)
#define OPERACAKE_PIN_OE(x) (x << 7)
#define OPERACAKE_PIN_U2CTRL1(x) (x << 6)
#define OPERACAKE_PIN_U2CTRL0(x) (x << 5)
#define OPERACAKE_PIN_U3CTRL1(x) (x << 4)
#define OPERACAKE_PIN_U3CTRL0(x) (x << 3)
#define OPERACAKE_PIN_U1CTRL(x) (x << 2)
#define OPERACAKE_PIN_LEDEN2(x) (x << 1)
#define OPERACAKE_PIN_LEDEN(x) (x << 0)
#define OPERACAKE_PORT_A1 (OPERACAKE_PIN_U2CTRL0(0) | OPERACAKE_PIN_U2CTRL1(0))
#define OPERACAKE_PORT_A2 (OPERACAKE_PIN_U2CTRL0(1) | OPERACAKE_PIN_U2CTRL1(0))
@ -49,10 +49,10 @@
#define OPERACAKE_PORT_B3 (OPERACAKE_PIN_U3CTRL0(0) | OPERACAKE_PIN_U3CTRL1(1))
#define OPERACAKE_PORT_B4 (OPERACAKE_PIN_U3CTRL0(1) | OPERACAKE_PIN_U3CTRL1(1))
#define OPERACAKE_SAMESIDE OPERACAKE_PIN_U1CTRL(1)
#define OPERACAKE_CROSSOVER OPERACAKE_PIN_U1CTRL(0)
#define OPERACAKE_EN_LEDS (OPERACAKE_PIN_LEDEN2(1) | OPERACAKE_PIN_LEDEN2(0))
#define OPERACAKE_GPIO_ENABLE OPERACAKE_PIN_OE(0)
#define OPERACAKE_SAMESIDE OPERACAKE_PIN_U1CTRL(1)
#define OPERACAKE_CROSSOVER OPERACAKE_PIN_U1CTRL(0)
#define OPERACAKE_EN_LEDS (OPERACAKE_PIN_LEDEN2(1) | OPERACAKE_PIN_LEDEN2(0))
#define OPERACAKE_GPIO_ENABLE OPERACAKE_PIN_OE(0)
#define OPERACAKE_GPIO_DISABLE OPERACAKE_PIN_OE(1)
#define OPERACAKE_REG_INPUT 0x00
@ -60,9 +60,9 @@
#define OPERACAKE_REG_POLARITY 0x02
#define OPERACAKE_REG_CONFIG 0x03
#define OPERACAKE_DEFAULT_OUTPUT (OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE \
| OPERACAKE_PORT_A1 | OPERACAKE_PORT_B1 \
| OPERACAKE_EN_LEDS)
#define OPERACAKE_DEFAULT_OUTPUT \
(OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE | OPERACAKE_PORT_A1 | \
OPERACAKE_PORT_B1 | OPERACAKE_EN_LEDS)
#define OPERACAKE_CONFIG_ALL_OUTPUT (0x00)
// Leave LED bits as outputs
#define OPERACAKE_CONFIG_GPIO_INPUTS (0x7C)
@ -80,9 +80,9 @@ static uint8_t current_range = INVALID_RANGE;
i2c_bus_t* const oc_bus = &i2c0;
enum operacake_switching_mode {
MODE_MANUAL = 0,
MODE_MANUAL = 0,
MODE_FREQUENCY = 1,
MODE_TIME = 2,
MODE_TIME = 2,
};
struct operacake_state {
@ -96,18 +96,20 @@ struct operacake_state operacake_boards[OPERACAKE_MAX_BOARDS];
bool allow_gpio_mode = true;
/* 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
address += OPERACAKE_ADDRESS_DEFAULT;
const uint8_t data_tx[] = { reg };
uint8_t data_rx[] = { 0x00 };
const uint8_t data_tx[] = {reg};
uint8_t data_rx[] = {0x00};
i2c_bus_transfer(bus, address, data_tx, 1, data_rx, 1);
return data_rx[0];
}
/* 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
address += OPERACAKE_ADDRESS_DEFAULT;
@ -115,19 +117,26 @@ 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);
}
uint8_t operacake_init(bool allow_gpio) {
uint8_t operacake_init(bool allow_gpio)
{
/* Find connected operacakes */
for (int addr = 0; addr < 8; addr++) {
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT);
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_write_reg(
oc_bus,
addr,
OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT);
operacake_write_reg(
oc_bus,
addr,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
uint8_t reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG);
operacake_boards[addr].present = (reg == OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_boards[addr].mode = MODE_MANUAL;
operacake_boards[addr].PA = OPERACAKE_PORT_A1;
operacake_boards[addr].PB = OPERACAKE_PORT_B1;
operacake_boards[addr].mode = MODE_MANUAL;
operacake_boards[addr].PA = OPERACAKE_PORT_A1;
operacake_boards[addr].PB = OPERACAKE_PORT_B1;
}
allow_gpio_mode = allow_gpio;
if (allow_gpio) {
@ -136,43 +145,48 @@ uint8_t operacake_init(bool allow_gpio) {
return 0;
}
bool operacake_is_board_present(uint8_t address) {
if (address >= OPERACAKE_MAX_BOARDS)
bool operacake_is_board_present(uint8_t address)
{
if (address >= OPERACAKE_MAX_BOARDS) {
return false;
}
return operacake_boards[address].present;
}
void operacake_get_boards(uint8_t *addresses) {
void operacake_get_boards(uint8_t* addresses)
{
int count = 0;
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
addresses[i] = OPERACAKE_ADDRESS_INVALID;
}
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
if (operacake_is_board_present(i))
if (operacake_is_board_present(i)) {
addresses[count++] = i;
}
}
}
uint8_t port_to_pins(uint8_t port) {
switch(port) {
case OPERACAKE_PA1:
return OPERACAKE_PORT_A1;
case OPERACAKE_PA2:
return OPERACAKE_PORT_A2;
case OPERACAKE_PA3:
return OPERACAKE_PORT_A3;
case OPERACAKE_PA4:
return OPERACAKE_PORT_A4;
uint8_t port_to_pins(uint8_t port)
{
switch (port) {
case OPERACAKE_PA1:
return OPERACAKE_PORT_A1;
case OPERACAKE_PA2:
return OPERACAKE_PORT_A2;
case OPERACAKE_PA3:
return OPERACAKE_PORT_A3;
case OPERACAKE_PA4:
return OPERACAKE_PORT_A4;
case OPERACAKE_PB1:
return OPERACAKE_PORT_B1;
case OPERACAKE_PB2:
return OPERACAKE_PORT_B2;
case OPERACAKE_PB3:
return OPERACAKE_PORT_B3;
case OPERACAKE_PB4:
return OPERACAKE_PORT_B4;
case OPERACAKE_PB1:
return OPERACAKE_PORT_B1;
case OPERACAKE_PB2:
return OPERACAKE_PORT_B2;
case OPERACAKE_PB3:
return OPERACAKE_PORT_B3;
case OPERACAKE_PB4:
return OPERACAKE_PORT_B4;
}
return 0xFF;
}
@ -188,8 +202,8 @@ uint8_t operacake_activate_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 1;
}
/* Ensure PA and PB are on opposite sides. */
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4))
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) ||
((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
return 1;
}
@ -207,35 +221,53 @@ uint8_t operacake_activate_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 0;
}
void operacake_set_mode(uint8_t address, uint8_t mode) {
if (address >= OPERACAKE_MAX_BOARDS)
void operacake_set_mode(uint8_t address, uint8_t mode)
{
if (address >= OPERACAKE_MAX_BOARDS) {
return;
}
operacake_boards[address].mode = mode;
current_range = INVALID_RANGE;
if (mode == MODE_TIME) {
// 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_OUTPUT, OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_OUTPUT,
OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS);
} else {
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_activate_ports(address, operacake_boards[address].PA, operacake_boards[address].PB);
operacake_write_reg(
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.
bool enable_sctimer = false;
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;
}
}
operacake_sctimer_enable(enable_sctimer);
}
uint8_t operacake_get_mode(uint8_t address) {
if (address >= OPERACAKE_MAX_BOARDS)
uint8_t operacake_get_mode(uint8_t address)
{
if (address >= OPERACAKE_MAX_BOARDS) {
return 0;
}
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;
}
/* Ensure PA and PB are on opposite sides. */
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4))
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) ||
((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
return 1;
}
@ -280,8 +312,9 @@ typedef struct {
static operacake_range ranges[MAX_OPERACAKE_RANGES * sizeof(operacake_range)];
static uint8_t range_idx = 0;
uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port) {
if(range_idx >= MAX_OPERACAKE_RANGES) {
uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port)
{
if (range_idx >= MAX_OPERACAKE_RANGES) {
return 1;
}
ranges[range_idx].freq_min = freq_min;
@ -296,20 +329,21 @@ uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port)
void operacake_clear_ranges(void)
{
range_idx = 0;
range_idx = 0;
}
#define FREQ_ONE_MHZ (1000000ull)
uint8_t operacake_set_range(uint32_t freq_mhz) {
if(range_idx == 0) {
uint8_t operacake_set_range(uint32_t freq_mhz)
{
if (range_idx == 0) {
return 1;
}
int range;
for(range=0; range<range_idx; range++) {
if((freq_mhz >= ranges[range].freq_min)
&& (freq_mhz <= ranges[range].freq_max)) {
for (range = 0; range < range_idx; range++) {
if ((freq_mhz >= ranges[range].freq_min) &&
(freq_mhz <= ranges[range].freq_max)) {
break;
}
}
@ -317,13 +351,17 @@ uint8_t operacake_set_range(uint32_t freq_mhz) {
if (range == range_idx) {
range--;
}
if(range == current_range) {
if (range == current_range) {
return 1;
}
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
if (operacake_is_board_present(i) && operacake_get_mode(i) == MODE_FREQUENCY) {
operacake_activate_ports(i, ranges[range].portA, ranges[range].portB);
if (operacake_is_board_present(i) &&
operacake_get_mode(i) == MODE_FREQUENCY) {
operacake_activate_ports(
i,
ranges[range].portA,
ranges[range].portB);
break;
}
}
@ -339,8 +377,9 @@ uint16_t gpio_test(uint8_t address)
{
uint8_t i, reg, bit_mask, gpio_mask = 0x1F;
uint16_t result = 0;
if(!allow_gpio_mode)
if (!allow_gpio_mode) {
return 0xFFFF;
}
scu_pinmux(SCU_PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_GPIO3_12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -358,17 +397,23 @@ uint16_t gpio_test(uint8_t address)
// Setup I2C to put it in GPIO mode
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_CONFIG,
OPERACAKE_CONFIG_GPIO_INPUTS);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_POLARITY,
OPERACAKE_POLARITY_NORMAL);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_GPIO_INPUTS);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_POLARITY,
OPERACAKE_POLARITY_NORMAL);
// clear state
for(i=0; i<5; i++) {
for (i = 0; i < 5; i++) {
gpio_output(&gpio_pins[i]);
gpio_write(&gpio_pins[i], 0);
}
// Test each pin separately
for(i=0; i<5; i++) {
for (i = 0; i < 5; i++) {
// Set pin high
gpio_write(&gpio_pins[i], 1);
// check input
@ -377,12 +422,12 @@ uint16_t gpio_test(uint8_t address)
reg &= gpio_mask;
bit_mask = 1 << i;
result <<= 1;
if(!(reg & bit_mask)) {
if (!(reg & bit_mask)) {
// Is the correct bit set?
result |= 1;
}
result <<= 1;
if(reg & ~bit_mask) {
if (reg & ~bit_mask) {
// Are any other bits set?
result |= 1;
}
@ -394,21 +439,27 @@ uint16_t gpio_test(uint8_t address)
reg >>= 2;
reg &= gpio_mask;
bit_mask = 1 << i;
if(reg & bit_mask) {
if (reg & bit_mask) {
// Is the correct bit clear?
result |= 1;
}
}
// clean up
for(i=0; i<5; i++) {
for (i = 0; i < 5; i++) {
gpio_input(&gpio_pins[i]);
}
// Put it back in to I2C mode and set default pins
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT);
return result;
}

View File

@ -23,8 +23,7 @@
#define __OPERACAKE_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
#include <stdint.h>
@ -44,7 +43,7 @@ extern "C"
uint8_t operacake_init(bool allow_gpio);
bool operacake_is_board_present(uint8_t address);
void operacake_get_boards(uint8_t *addresses);
void operacake_get_boards(uint8_t* addresses);
void operacake_set_mode(uint8_t address, uint8_t mode);
uint8_t operacake_get_mode(uint8_t address);
uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB);

View File

@ -30,9 +30,8 @@
#include <libopencm3/lpc43xx/gima.h>
#include "sct.h"
#define U1CTRL_SET SCT_OUT14_SET
#define U1CTRL_CLR SCT_OUT14_CLR
#define U1CTRL_SET SCT_OUT14_SET
#define U1CTRL_CLR SCT_OUT14_CLR
#define U2CTRL0_SET SCT_OUT13_SET
#define U2CTRL0_CLR SCT_OUT13_CLR
#define U2CTRL1_SET SCT_OUT12_SET
@ -53,7 +52,8 @@ static uint32_t default_output = 0;
* 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.
*/
void operacake_sctimer_init() {
void operacake_sctimer_init()
{
// We start by resetting the SCTimer
RESET_CTRL1 = RESET_CTRL1_SCT_RST;
@ -67,33 +67,39 @@ void operacake_sctimer_init() {
// this delay may need to be increased.
delay(8);
// Pin definitions for the HackRF
// 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
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
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
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
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
SGPIO_OUT_MUX_CFG12 =
SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode
SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe
SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode
SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe
SGPIO_GPIO_OENREG |= BIT12;
// Use the GIMA to connect the SGPIO clock to the SCTimer
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
SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT
| SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK
| SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1;
SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT | SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK |
SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1;
// Halt the SCTimer to enable it to be configured
SCT_CTRL = SCT_CTRL_HALT_L(1);
@ -108,42 +114,45 @@ void operacake_sctimer_init() {
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 bit1 = (port >> 1) & 1;
int bit2 = (port >> 2) & 1;
return (bit0 << 11) | (bit0 << 13) |
(bit1 << 8) | (bit1 << 12) |
(((~bit2)&1) << 14);
return (bit0 << 11) | (bit0 << 13) | (bit1 << 8) | (bit1 << 12) |
(((~bit2) & 1) << 14);
}
void operacake_sctimer_enable(bool enable) {
void operacake_sctimer_enable(bool enable)
{
SCT_CTRL = SCT_CTRL_HALT_L(1);
SCT_STATE = enable;
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);
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++) {
// Enable event i in state 1, set to match on match register i
SCT_EVn_STATE(i) = SCT_EVn_STATE_STATEMSK1(1);
SCT_EVn_CTRL(i) = SCT_EVn_CTRL_COMBMODE_MATCH | SCT_EVn_CTRL_MATCHSEL(i);
SCT_EVn_CTRL(i) = SCT_EVn_CTRL_COMBMODE_MATCH | SCT_EVn_CTRL_MATCHSEL(i);
// Calculate the counter value to match on
counter += times[i].dwell;
// Wrapping from SCT_LIMIT seems to add an extra cycle,
// so we reduce the counter value for the first event.
if (i == 0)
if (i == 0) {
counter -= 1;
}
SCT_MATCHn(i) = counter;
SCT_MATCHn(i) = counter;
SCT_MATCHRELn(i) = counter;
// The match event selects the *next* port, so retreive that here.
@ -151,7 +160,7 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
if (i == n - 1) {
port = times[0].port;
} else {
port = times[i+1].port;
port = times[i + 1].port;
}
int bit0 = (port >> 0) & 1;
@ -159,15 +168,15 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
int bit2 = (port >> 2) & 1;
// Find bits to set/clear on event i
bit0_set |= SCT_OUTn_SETm( bit0, i);
bit0_set |= SCT_OUTn_SETm(bit0, i);
bit0_clr |= SCT_OUTn_CLRm(~bit0, i);
bit1_set |= SCT_OUTn_SETm( bit1, i);
bit1_set |= SCT_OUTn_SETm(bit1, i);
bit1_clr |= SCT_OUTn_CLRm(~bit1, i);
// (U1CTRL is inverted)
bit2_set |= SCT_OUTn_SETm(~bit2, i);
bit2_clr |= SCT_OUTn_CLRm( bit2, i);
bit2_clr |= SCT_OUTn_CLRm(bit2, i);
}
// Apply event set/clear mappings
@ -179,20 +188,21 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
U2CTRL1_CLR = bit1_clr;
U3CTRL1_SET = bit1_set;
U3CTRL1_CLR = bit1_clr;
U1CTRL_SET = bit2_set;
U1CTRL_CLR = bit2_clr;
U1CTRL_SET = bit2_set;
U1CTRL_CLR = bit2_clr;
// Set output pins to select the first port in the list
default_output = operacake_sctimer_port_to_output(times[0].port);
SCT_OUTPUT = default_output;
// Reset counter on final event
SCT_LIMIT = (1 << (n-1));
SCT_LIMIT = (1 << (n - 1));
SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
}
void operacake_sctimer_stop() {
void operacake_sctimer_stop()
{
// Halt timer
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
* same antenna selected each time.
*/
void operacake_sctimer_reset_state() {
void operacake_sctimer_reset_state()
{
SCT_CTRL |= SCT_CTRL_HALT_L(1);
// Clear the counter value

View File

@ -34,7 +34,7 @@ struct operacake_dwell_times {
void operacake_sctimer_init();
void operacake_sctimer_enable(bool enable);
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);
void operacake_sctimer_stop();
void operacake_sctimer_reset_state();

View File

@ -26,18 +26,24 @@
#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 */
delay(milliseconds * 40800);
delay(milliseconds * 40800);
}
static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */
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)) 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_wrx = GPIO(1, 10); /* P2_9 */
static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */
// clang-format off
static struct gpio_t gpio_io_stbx = GPIO(5, 0); /* P2_0 */
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))
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_wrx = GPIO(1, 10); /* P2_9 */
static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */
// clang-format on
typedef struct portapack_if_t {
gpio_t gpio_dir;
@ -50,39 +56,44 @@ typedef struct portapack_if_t {
} portapack_if_t;
static portapack_if_t portapack_if = {
.gpio_dir = &gpio_dir,
.gpio_lcd_rdx = &gpio_lcd_rdx,
.gpio_lcd_wrx = &gpio_lcd_wrx,
.gpio_io_stbx = &gpio_io_stbx,
.gpio_addr = &gpio_addr,
.gpio_port_data = GPIO_LPC_PORT(3),
.io_reg = 0x03,
.gpio_dir = &gpio_dir,
.gpio_lcd_rdx = &gpio_lcd_rdx,
.gpio_lcd_wrx = &gpio_lcd_wrx,
.gpio_io_stbx = &gpio_io_stbx,
.gpio_addr = &gpio_addr,
.gpio_port_data = GPIO_LPC_PORT(3),
.io_reg = 0x03,
};
/* NOTE: Code below assumes the shift value is "8". */
#define GPIO_DATA_SHIFT (8)
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;
}
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);
}
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 that bits 15 through 8 are masked. */
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;
gpio_set(portapack_if.gpio_dir);
}
static void portapack_dir_write() {
static void portapack_dir_write()
{
gpio_clear(portapack_if.gpio_dir);
portapack_if.gpio_port_data->dir |= gpio_data_mask;
/* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin
@ -93,66 +104,76 @@ 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);
}
static void portapack_lcd_rd_deassert() {
static void portapack_lcd_rd_deassert()
{
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);
}
static void portapack_lcd_wr_deassert() {
static void portapack_lcd_wr_deassert()
{
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);
}
static void portapack_io_stb_deassert() {
static void portapack_io_stb_deassert()
{
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);
}
static void portapack_lcd_command(const uint32_t value) {
portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */
portapack_dir_write(); /* Turn around data bus, MCU->CPLD */
portapack_addr(0); /* Indicate command */
static void portapack_lcd_command(const uint32_t value)
{
portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */
portapack_dir_write(); /* Turn around data bus, MCU->CPLD */
portapack_addr(0); /* Indicate command */
__asm__("nop");
__asm__("nop");
__asm__("nop");
portapack_lcd_wr_assert(); /* Latch high byte */
portapack_lcd_wr_assert(); /* Latch high byte */
portapack_data_write_low(value); /* Drive low byte (pass-through) */
portapack_data_write_low(value); /* Drive low byte (pass-through) */
__asm__("nop");
__asm__("nop");
__asm__("nop");
portapack_lcd_wr_deassert(); /* Complete write operation */
portapack_lcd_wr_deassert(); /* Complete write operation */
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.
portapack_data_write_high(value); /* Drive high byte */
portapack_data_write_high(value); /* Drive high byte */
__asm__("nop");
portapack_lcd_wr_assert(); /* Latch high byte */
portapack_lcd_wr_assert(); /* Latch high byte */
portapack_data_write_low(value); /* Drive low byte (pass-through) */
portapack_data_write_low(value); /* Drive low byte (pass-through) */
__asm__("nop");
__asm__("nop");
__asm__("nop");
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_dir_write();
portapack_addr(address);
@ -166,7 +187,8 @@ static void portapack_io_write(const bool address, const uint_fast16_t value) {
portapack_io_stb_deassert();
}
static void portapack_if_init() {
static void portapack_if_init()
{
portapack_data_mask_set();
portapack_data_write_high(0);
@ -193,16 +215,17 @@ static void portapack_if_init() {
scu_pinmux(SCU_PINMUX_PP_D6, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
scu_pinmux(SCU_PINMUX_PP_D7, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
scu_pinmux(SCU_PINMUX_PP_DIR, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_PP_DIR, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_PP_LCD_RDX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_PP_LCD_WRX, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_PP_IO_STBX, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_PP_ADDR, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
scu_pinmux(SCU_PINMUX_PP_ADDR, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL);
/* scu_pinmux(SCU_PINMUX_PP_LCD_TE, 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_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(
const uint_fast8_t command,
const uint8_t* data,
const size_t data_count
) {
const size_t data_count)
{
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]);
}
}
static void portapack_lcd_sleep_out() {
static void portapack_lcd_sleep_out()
{
const uint8_t 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
@ -227,56 +251,68 @@ static void portapack_lcd_sleep_out() {
portapack_sleep_milliseconds(120);
}
static void portapack_lcd_display_on() {
static void portapack_lcd_display_on()
{
const uint8_t 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[] = {};
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) {
const uint8_t data[] = {
(start >> 8), (start & 0xff),
(end >> 8), (end & 0xff)
};
static void portapack_lcd_set(
const uint_fast8_t command,
const uint_fast16_t start,
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));
}
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);
}
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);
}
static void portapack_lcd_start_ram_write(
const ui_rect_t rect
) {
portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1);
static void portapack_lcd_start_ram_write(const ui_rect_t rect)
{
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_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);
}
static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n) {
while(n--) {
static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n)
{
while (n--) {
portapack_lcd_write_data(c.v);
}
}
static void portapack_lcd_wake() {
static void portapack_lcd_wake()
{
portapack_lcd_sleep_out();
portapack_lcd_display_on();
}
static void portapack_lcd_reset() {
static void portapack_lcd_reset()
{
portapack_lcd_reset_state(false);
portapack_sleep_milliseconds(1);
portapack_lcd_reset_state(true);
@ -285,7 +321,8 @@ static void portapack_lcd_reset() {
portapack_sleep_milliseconds(120);
}
static void portapack_lcd_init() {
static void portapack_lcd_init()
{
// LCDs are configured for IM[2:0] = 001
// 8080-I system, 16-bit parallel bus
@ -296,30 +333,30 @@ static void portapack_lcd_init() {
// Power control B
// 0
// PCEQ=1, DRV_ena=0, Power control=3
const uint8_t cmd_cf[] = { 0x00, 0xD9, 0x30 };
const uint8_t cmd_cf[] = {0x00, 0xD9, 0x30};
portapack_lcd_data_write_command_and_data(0xCF, cmd_cf, ARRAY_SIZEOF(cmd_cf));
// Power on sequence control
const uint8_t cmd_ed[] = { 0x64, 0x03, 0x12, 0x81 };
const uint8_t cmd_ed[] = {0x64, 0x03, 0x12, 0x81};
portapack_lcd_data_write_command_and_data(0xED, cmd_ed, ARRAY_SIZEOF(cmd_ed));
// Driver timing control A
const uint8_t cmd_e8[] = { 0x85, 0x10, 0x78 };
const uint8_t cmd_e8[] = {0x85, 0x10, 0x78};
portapack_lcd_data_write_command_and_data(0xE8, cmd_e8, ARRAY_SIZEOF(cmd_e8));
// Power control A
const uint8_t cmd_cb[] = { 0x39, 0x2C, 0x00, 0x34, 0x02 };
const uint8_t cmd_cb[] = {0x39, 0x2C, 0x00, 0x34, 0x02};
portapack_lcd_data_write_command_and_data(0xCB, cmd_cb, ARRAY_SIZEOF(cmd_cb));
// Pump ratio control
const uint8_t cmd_f7[] = { 0x20 };
const uint8_t cmd_f7[] = {0x20};
portapack_lcd_data_write_command_and_data(0xF7, cmd_f7, ARRAY_SIZEOF(cmd_f7));
// Driver timing control B
const uint8_t cmd_ea[] = { 0x00, 0x00 };
const uint8_t cmd_ea[] = {0x00, 0x00};
portapack_lcd_data_write_command_and_data(0xEA, cmd_ea, ARRAY_SIZEOF(cmd_ea));
const uint8_t cmd_b1[] = { 0x00, 0x1B };
const uint8_t cmd_b1[] = {0x00, 0x1B};
portapack_lcd_data_write_command_and_data(0xB1, cmd_b1, ARRAY_SIZEOF(cmd_b1));
// Blanking Porch Control
@ -327,7 +364,7 @@ static void portapack_lcd_init() {
// VBP = 0b0000010 = 2 (number of HSYNC of vertical back porch)
// HFP = 0b0001010 = 10 (number of DOTCLOCK of horizontal front porch)
// HBP = 0b0010100 = 20 (number of DOTCLOCK of horizontal back porch)
const uint8_t cmd_b5[] = { 0x02, 0x02, 0x0a, 0x14 };
const uint8_t cmd_b5[] = {0x02, 0x02, 0x0a, 0x14};
portapack_lcd_data_write_command_and_data(0xB5, cmd_b5, ARRAY_SIZEOF(cmd_b5));
// Display Function Control
@ -340,42 +377,42 @@ static void portapack_lcd_init() {
// REV = 1 (normally white)
// NL = 0b100111 (default)
// PCDIV = 0b000000 (default?)
const uint8_t cmd_b6[] = { 0x0A, 0xA2, 0x27, 0x00 };
const uint8_t cmd_b6[] = {0x0A, 0xA2, 0x27, 0x00};
portapack_lcd_data_write_command_and_data(0xB6, cmd_b6, ARRAY_SIZEOF(cmd_b6));
// Power Control 1
//VRH[5:0]
const uint8_t cmd_c0[] = { 0x1B };
const uint8_t cmd_c0[] = {0x1B};
portapack_lcd_data_write_command_and_data(0xC0, cmd_c0, ARRAY_SIZEOF(cmd_c0));
// Power Control 2
//SAP[2:0];BT[3:0]
const uint8_t cmd_c1[] = { 0x12 };
const uint8_t cmd_c1[] = {0x12};
portapack_lcd_data_write_command_and_data(0xC1, cmd_c1, ARRAY_SIZEOF(cmd_c1));
// VCOM Control 1
const uint8_t cmd_c5[] = { 0x32, 0x3C };
const uint8_t cmd_c5[] = {0x32, 0x3C};
portapack_lcd_data_write_command_and_data(0xC5, cmd_c5, ARRAY_SIZEOF(cmd_c5));
// VCOM Control 2
const uint8_t cmd_c7[] = { 0x9B };
const uint8_t cmd_c7[] = {0x9B};
portapack_lcd_data_write_command_and_data(0xC7, cmd_c7, ARRAY_SIZEOF(cmd_c7));
// Memory Access Control
// Invert X and Y memory access order, so upper-left of
// screen is (0,0) when writing to display.
const uint8_t cmd_36[] = {
(1 << 7) | // MY=1
(1 << 6) | // MX=1
(0 << 5) | // MV=0
(1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic
(1 << 3) // BGR=1: For Kingtech LCD, BGR filter.
(1 << 7) | // MY=1
(1 << 6) | // MX=1
(0 << 5) | // MV=0
(1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic
(1 << 3) // BGR=1: For Kingtech LCD, BGR filter.
};
portapack_lcd_data_write_command_and_data(0x36, cmd_36, ARRAY_SIZEOF(cmd_36));
// COLMOD: Pixel Format Set
// DPI=101 (16 bits/pixel), DBI=101 (16 bits/pixel)
const uint8_t cmd_3a[] = { 0x55 };
const uint8_t cmd_3a[] = {0x55};
portapack_lcd_data_write_command_and_data(0x3A, cmd_3a, ARRAY_SIZEOF(cmd_3a));
//portapack_lcd_data_write_command_and_data(0xF6, { 0x01, 0x30 });
@ -386,59 +423,84 @@ static void portapack_lcd_init() {
// RM=0 (system interface/VSYNC interface)
// DM[1:0]=00 (internal clock operation)
// ENDIAN=0 (doesn't matter with 16-bit interface)
const uint8_t cmd_f6[] = { 0x01, 0x30, 0x00 };
const uint8_t cmd_f6[] = {0x01, 0x30, 0x00};
portapack_lcd_data_write_command_and_data(0xF6, cmd_f6, ARRAY_SIZEOF(cmd_f6));
// 3Gamma Function Disable
const uint8_t cmd_f2[] = { 0x00 };
const uint8_t cmd_f2[] = {0x00};
portapack_lcd_data_write_command_and_data(0xF2, cmd_f2, ARRAY_SIZEOF(cmd_f2));
// Gamma curve selected
const uint8_t cmd_26[] = { 0x01 };
const uint8_t cmd_26[] = {0x01};
portapack_lcd_data_write_command_and_data(0x26, cmd_26, ARRAY_SIZEOF(cmd_26));
// Set Gamma
const uint8_t cmd_e0[] = {
0x0F, 0x1D, 0x19, 0x0E, 0x10, 0x07, 0x4C, 0x63,
0x3F, 0x03, 0x0D, 0x00, 0x26, 0x24, 0x04
};
0x0F,
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));
// Set Gamma
const uint8_t cmd_e1[] = {
0x00, 0x1C, 0x1F, 0x02, 0x0F, 0x03, 0x35, 0x25,
0x47, 0x04, 0x0C, 0x0B, 0x29, 0x2F, 0x05
};
0x00,
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_wake();
// Turn on Tearing Effect Line (TE) output signal.
const uint8_t cmd_35[] = { 0b00000000 };
const uint8_t cmd_35[] = {0b00000000};
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_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;
portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0);
portapack_io_write(1, portapack_if.io_reg);
}
void portapack_fill_rectangle(
const ui_rect_t rect,
const ui_color_t color
) {
void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color)
{
portapack_lcd_start_ram_write(rect);
portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height);
}
void portapack_clear_display(const ui_color_t color) {
const ui_rect_t rect_screen = { { 0, 0 }, { 240, 320 } };
void portapack_clear_display(const ui_color_t color)
{
const ui_rect_t rect_screen = {{0, 0}, {240, 320}};
portapack_fill_rectangle(rect_screen, color);
}
@ -446,33 +508,27 @@ void portapack_draw_bitmap(
const ui_point_t point,
const ui_bitmap_t bitmap,
const ui_color_t foreground,
const ui_color_t background
) {
const ui_rect_t rect = {
.point = point,
.size = bitmap.size
};
const ui_color_t background)
{
const ui_rect_t rect = {.point = point, .size = bitmap.size};
portapack_lcd_start_ram_write(rect);
const size_t count = bitmap.size.width * bitmap.size.height;
for(size_t i=0; i<count; i++) {
for (size_t i = 0; i < count; i++) {
const uint8_t pixel = bitmap.data[i >> 3] & (1U << (i & 0x7));
portapack_lcd_write_pixel(pixel ? foreground : background);
}
}
ui_bitmap_t portapack_font_glyph(
const ui_font_t* const font,
const char c
) {
if( c >= font->c_start ) {
ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c)
{
if (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 = {
.size = font->glyph_size,
.data = &font->data[index * font->data_stride]
};
.data = &font->data[index * font->data_stride]};
return bitmap;
}
}
@ -484,7 +540,8 @@ ui_bitmap_t portapack_font_glyph(
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);
// 8 ns TMS/TDI to TCK setup
@ -517,11 +574,12 @@ static bool jtag_pp_tck(const bool tms_value) {
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;
size_t bit_in_index = count - 1;
size_t bit_out_index = 0;
while(bit_out_index < count) {
while (bit_out_index < count) {
const uint32_t tdo = jtag_pp_tck((tms_bits >> bit_in_index) & 1) & 1;
result |= (tdo << bit_out_index);
@ -532,7 +590,8 @@ static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) {
return result;
}
static uint32_t jtag_pp_idcode(void) {
static uint32_t jtag_pp_idcode(void)
{
cpld_jtag_take(&jtag_cpld);
/* TODO: Check if PortaPack TMS is floating or driven by an external device. */
@ -552,21 +611,23 @@ static uint32_t jtag_pp_idcode(void) {
return idcode;
}
static bool portapack_detect(void) {
static bool portapack_detect(void)
{
return jtag_pp_idcode() == 0x020A50DD;
}
static const portapack_t portapack_instance = {
};
static const portapack_t portapack_instance = {};
static const portapack_t* portapack_pointer = NULL;
const portapack_t* portapack(void) {
const portapack_t* portapack(void)
{
return portapack_pointer;
}
void portapack_init(void) {
if( portapack_detect() ) {
void portapack_init(void)
{
if (portapack_detect()) {
portapack_if_init();
portapack_lcd_reset();
portapack_lcd_init();

View File

@ -73,10 +73,7 @@ void portapack_backlight(const bool on);
void portapack_reference_oscillator(const bool on) __attribute__((weak));
void portapack_fill_rectangle(
const ui_rect_t rect,
const ui_color_t color
);
void portapack_fill_rectangle(const ui_rect_t rect, 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_bitmap_t bitmap,
const ui_color_t foreground,
const ui_color_t background
);
const ui_color_t background);
ui_bitmap_t portapack_font_glyph(
const ui_font_t* const font,
const char c
);
ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c);
#endif/*__PORTAPACK_H__*/
#endif /*__PORTAPACK_H__*/

View File

@ -4,9 +4,9 @@
#include <stdint.h>
// Local function: Get next nibble.
static int ctr = 0; // offset for next nibble
static int ctr = 0; // offset for next nibble
static int hilo = 0; // 0= high nibble next, 1=low nibble next
static const uint8_t *data;
static const uint8_t* data;
#define MAXCHR (30 * 20)
static uint8_t charBuf[MAXCHR];
@ -43,24 +43,24 @@ static int upl(int off)
return retval;
}
uint8_t *rad1o_pk_decode(const uint8_t *ldata, int *len)
uint8_t* rad1o_pk_decode(const uint8_t* ldata, int* len)
{
ctr = 0;
hilo = 0;
data = ldata;
int length = *len; // Length of character bytestream
int height; // Height of character in bytes
int hoff; // bit position for non-integer heights
uint8_t *bufptr = charBuf; // Output buffer for decoded character
int length = *len; // Length of character bytestream
int height; // Height of character in bytes
int hoff; // bit position for non-integer heights
uint8_t* bufptr = charBuf; // Output buffer for decoded character
height = (rad1o_getFontHeight() - 1) / 8 + 1;
hoff = rad1o_getFontHeight() % 8;
#define DYN (12) // Decoder parameter: Fixed value for now.
#define DYN (12) // Decoder parameter: Fixed value for now.
int repeat = 0; // Decoder internal: repeat colum?
int curbit = 0; // Decoder internal: current bit (1 or 0)
int pos = 0; // Decoder internal: current bit position (0..7)
int nyb; // Decoder internal: current nibble / value
int pos = 0; // Decoder internal: current bit position (0..7)
int nyb; // Decoder internal: current nibble / value
if (data[ctr] >> 4 == 14) { // Char starts with 1-bits.
gnn();
@ -104,13 +104,10 @@ uint8_t *rad1o_pk_decode(const uint8_t *ldata, int *len)
if (pos == 8) {
bufptr++;
if ((bufptr - charBuf) % height ==
0) { // End of column?
if ((bufptr - charBuf) % height == 0) { // End of column?
while (repeat > 0) {
for (int y = 0; y < height;
y++) {
bufptr[0] =
bufptr[-height];
for (int y = 0; y < height; y++) {
bufptr[0] = bufptr[-height];
bufptr++;
};
repeat--;

View File

@ -3,6 +3,6 @@
#include <stdint.h>
uint8_t *rad1o_pk_decode(const uint8_t *data, int *len);
uint8_t* rad1o_pk_decode(const uint8_t* data, int* len);
#endif

View File

@ -16,8 +16,8 @@ static void delayms(const uint32_t milliseconds)
delay(milliseconds * 40800);
}
static struct gpio_t gpio_lcd_cs = GPIO(4, 12); /* P9_0 */
static struct gpio_t gpio_lcd_bl_en = GPIO(0, 8); /* P1_1 */
static struct gpio_t gpio_lcd_cs = GPIO(4, 12); /* P9_0 */
static struct gpio_t gpio_lcd_bl_en = GPIO(0, 8); /* P1_1 */
static struct gpio_t gpio_lcd_reset = GPIO(5, 17); /* P9_4 */
/**************************************************************************/
@ -44,9 +44,16 @@ static void select()
uint8_t serial_clock_rate = 1;
uint8_t clock_prescale_rate = 12;
ssp_init(LCD_SSP, 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);
ssp_init(
LCD_SSP,
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);
}
@ -87,18 +94,25 @@ void rad1o_lcdInit(void)
/* The controller is a PCF8833 - documentation can be found online. */
static uint8_t initseq_d[] = {
0x11, // SLEEP_OUT (wake up)
0x3A, 2, // mode 8bpp (2= 8bpp, 3= 12bpp, 5= 16bpp)
0x36, 0b11000000, // my,mx,v,lao,rgb,x,x,x
0x25, 0x3a, // set contrast
0x3A,
2, // mode 8bpp (2= 8bpp, 3= 12bpp, 5= 16bpp)
0x36,
0b11000000, // my,mx,v,lao,rgb,x,x,x
0x25,
0x3a, // set contrast
0x29, // display on
0x03, // BSTRON (booster voltage)
0x2A, 1, RESX, 0x2B, 1, 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);
0x2A,
1,
RESX,
0x2B,
1,
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);
write(0, 0x01); /* most color displays need the pause */
delayms(10);
@ -139,7 +153,7 @@ static uint8_t getPixel(uint8_t x, uint8_t y)
return lcdBuffer[y * RESX + x];
}
uint8_t *rad1o_lcdGetBuffer(void)
uint8_t* rad1o_lcdGetBuffer(void)
{
return lcdBuffer;
}

View File

@ -8,14 +8,14 @@
#define RESX 130
#define RESY 130
#define TYPE_CMD 0
#define TYPE_CMD 0
#define TYPE_DATA 1
#define _PIN(pin, func, ...) pin
#define _PIN(pin, func, ...) pin
#define _FUNC(pin, func, ...) func
#define SETUPpin(args...) scu_pinmux(_PIN(args), _FUNC(args))
#define SETUPpin(args...) scu_pinmux(_PIN(args), _FUNC(args))
#define LCD_DI P1_4, SCU_CONF_FUNCTION5 | SCU_SSP_IO
#define LCD_DI P1_4, SCU_CONF_FUNCTION5 | SCU_SSP_IO
#define LCD_SCK P1_19, SCU_CONF_FUNCTION1 | SCU_SSP_IO
#define LCD_SSP SSP1_NUM
@ -25,6 +25,6 @@ void rad1o_lcdDeInit(void);
void rad1o_lcdFill(uint8_t f);
void rad1o_lcdDisplay(void);
void rad1o_lcdSetPixel(uint8_t x, uint8_t y, uint8_t f);
uint8_t *rad1o_lcdGetBuffer(void);
uint8_t* rad1o_lcdGetBuffer(void);
#endif

View File

@ -2,11 +2,11 @@
#include <stdint.h>
#define SWAP(p1, p2) \
do { \
uint8_t SWAP = p1; \
p1 = p2; \
p2 = SWAP; \
#define SWAP(p1, p2) \
do { \
uint8_t SWAP = p1; \
p1 = p2; \
p2 = SWAP; \
} while (0)
void rad1o_drawHLine(uint8_t y, uint8_t x1, uint8_t x2, uint8_t color)

View File

@ -11,13 +11,13 @@ typedef struct {
} FONT_CHAR_INFO;
struct FONT_DEF {
uint8_t u8Width; /* Character width for storage */
uint8_t u8Height; /* Character height for storage */
uint8_t u8FirstChar; /* The first character available */
uint8_t u8LastChar; /* The last character available */
const uint8_t *au8FontTable; /* Font table start address in memory */
const FONT_CHAR_INFO *charInfo; /* Pointer to array of char information */
const uint16_t *charExtra; /* Pointer to array of extra char info */
uint8_t u8Width; /* Character width for storage */
uint8_t u8Height; /* Character height for storage */
uint8_t u8FirstChar; /* The first character available */
uint8_t u8LastChar; /* The last character available */
const uint8_t* au8FontTable; /* Font table start address in memory */
const FONT_CHAR_INFO* charInfo; /* Pointer to array of char information */
const uint16_t* charExtra; /* Pointer to array of extra char info */
};
struct EXTFONT {
@ -26,9 +26,9 @@ struct EXTFONT {
struct FONT_DEF def;
};
typedef const struct FONT_DEF *FONT;
typedef const struct FONT_DEF* FONT;
#define FONT_DEFAULT 0
#define FONT_DEFAULT 0
#define FONT_INTERNAL 1
#define FONT_EXTERNAL 2

View File

@ -7,7 +7,7 @@
static int32_t x = 0;
static int32_t y = 0;
void rad1o_lcdPrint(const char *string)
void rad1o_lcdPrint(const char* string)
{
x = rad1o_DoString(x, y, string);
}

View File

@ -3,7 +3,7 @@
#include <stdint.h>
void rad1o_lcdPrint(const char *string);
void rad1o_lcdPrint(const char* string);
void rad1o_lcdNl(void);
void rad1o_lcdClear(void);
void rad1o_lcdMoveCrsr(int32_t dx, int32_t dy);

View File

@ -7,7 +7,7 @@
#include <string.h>
/* Global Variables */
static const struct FONT_DEF *font = NULL;
static const struct FONT_DEF* font = NULL;
static struct EXTFONT efont;
@ -21,7 +21,7 @@ void rad1o_setTextColor(uint8_t bg, uint8_t fg)
color_fg = fg;
}
void rad1o_setIntFont(const struct FONT_DEF *newfont)
void rad1o_setIntFont(const struct FONT_DEF* newfont)
{
memcpy(&efont.def, newfont, sizeof(struct FONT_DEF));
efont.type = FONT_INTERNAL;
@ -69,7 +69,7 @@ int rad1o_DoChar(int sx, int sy, int c)
char height = (font->u8Height - 1) / 8 + 1;
char hoff = (8 - (font->u8Height % 8)) % 8;
const uint8_t *data;
const uint8_t* data;
int width, preblank = 0, postblank = 0;
do { /* Get Character data */
/* Get intex into character list */
@ -98,19 +98,17 @@ int rad1o_DoChar(int sx, int sy, int c)
data = &font->au8FontTable[toff + 3];
width = (width - 3 / height);
} else {
data = rad1o_pk_decode(
&font->au8FontTable[toff], &width);
data = rad1o_pk_decode(&font->au8FontTable[toff], &width);
}
} else {
toff = (c)*font->u8Width * 1;
toff = (c) *font->u8Width * 1;
width = font->u8Width;
data = &font->au8FontTable[toff];
};
} while (0);
#define xy_(x, y) \
((x < 0 || y < 0 || x >= RESX || y >= RESY) ? 0 : (y)*RESX + (x))
#define xy_(x, y) ((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)))
int x = 0;
@ -120,7 +118,7 @@ int rad1o_DoChar(int sx, int sy, int c)
sx += preblank;
uint8_t *lcdBuffer = rad1o_lcdGetBuffer();
uint8_t* lcdBuffer = rad1o_lcdGetBuffer();
/* per line */
for (int y = hoff; y < height * 8; y++) {
if (sy + y >= RESY)
@ -152,9 +150,9 @@ int rad1o_DoChar(int sx, int sy, int c)
return sx + (width + postblank);
}
int rad1o_DoString(int sx, int sy, const char *s)
int rad1o_DoString(int sx, int sy, const char* s)
{
const char *c;
const char* c;
for (c = s; *c != 0; c++) {
sx = rad1o_DoChar(sx, sy, *c);
};

View File

@ -4,8 +4,8 @@
#include "fonts.h"
void rad1o_setTextColor(uint8_t bg, uint8_t fg);
void rad1o_setIntFont(const struct FONT_DEF *font);
void rad1o_setIntFont(const struct FONT_DEF* font);
int rad1o_getFontHeight(void);
int rad1o_DoString(int sx, int sy, const char *s);
int rad1o_DoString(int sx, int sy, const char* s);
int rad1o_DoChar(int sx, int sy, int c);
#endif

View File

@ -41,104 +41,104 @@
/* System 7x8 */
const uint8_t au8Font7x8[] = {
0, 0, 0, 0, 0, 0, 0, //' '
0, 6, 95, 95, 6, 0, 0, //'!'
0, 7, 7, 0, 7, 7, 0, //'"'
20, 127, 127, 20, 127, 127, 20, //'#'
36, 46, 107, 107, 58, 18, 0, //'$'
70, 102, 48, 24, 12, 102, 98, //'%'
48, 122, 79, 93, 55, 122, 72, //'&'
4, 7, 3, 0, 0, 0, 0, //'''
0, 28, 62, 99, 65, 0, 0, //'('
0, 65, 99, 62, 28, 0, 0, //')'
8, 42, 62, 28, 28, 62, 42, //'*'
8, 8, 62, 62, 8, 8, 0, //'+'
0, 128, 224, 96, 0, 0, 0, //','
8, 8, 8, 8, 8, 8, 0, //'-'
0, 0, 96, 96, 0, 0, 0, //'.'
96, 48, 24, 12, 6, 3, 1, //'/'
62, 127, 113, 89, 77, 127, 62, //'0'
64, 66, 127, 127, 64, 64, 0, //'1'
98, 115, 89, 73, 111, 102, 0, //'2'
34, 99, 73, 73, 127, 54, 0, //'3'
24, 28, 22, 83, 127, 127, 80, //'4'
39, 103, 69, 69, 125, 57, 0, //'5'
60, 126, 75, 73, 121, 48, 0, //'6'
3, 3, 113, 121, 15, 7, 0, //'7'
54, 127, 73, 73, 127, 54, 0, //'8'
6, 79, 73, 105, 63, 30, 0, //'9'
0, 0, 102, 102, 0, 0, 0, //':'
0, 128, 230, 102, 0, 0, 0, //';'
8, 28, 54, 99, 65, 0, 0, //'<'
36, 36, 36, 36, 36, 36, 0, //'='
0, 65, 99, 54, 28, 8, 0, //'>'
2, 3, 81, 89, 15, 6, 0, //'?'
62, 127, 65, 93, 93, 31, 30, //'@'
124, 126, 19, 19, 126, 124, 0, //'A'
65, 127, 127, 73, 73, 127, 54, //'B'
28, 62, 99, 65, 65, 99, 34, //'C'
65, 127, 127, 65, 99, 62, 28, //'D'
65, 127, 127, 73, 93, 65, 99, //'E'
65, 127, 127, 73, 29, 1, 3, //'F'
0, 0, 0, 0, 0, 0, 0, //' '
0, 6, 95, 95, 6, 0, 0, //'!'
0, 7, 7, 0, 7, 7, 0, //'"'
20, 127, 127, 20, 127, 127, 20, //'#'
36, 46, 107, 107, 58, 18, 0, //'$'
70, 102, 48, 24, 12, 102, 98, //'%'
48, 122, 79, 93, 55, 122, 72, //'&'
4, 7, 3, 0, 0, 0, 0, //'''
0, 28, 62, 99, 65, 0, 0, //'('
0, 65, 99, 62, 28, 0, 0, //')'
8, 42, 62, 28, 28, 62, 42, //'*'
8, 8, 62, 62, 8, 8, 0, //'+'
0, 128, 224, 96, 0, 0, 0, //','
8, 8, 8, 8, 8, 8, 0, //'-'
0, 0, 96, 96, 0, 0, 0, //'.'
96, 48, 24, 12, 6, 3, 1, //'/'
62, 127, 113, 89, 77, 127, 62, //'0'
64, 66, 127, 127, 64, 64, 0, //'1'
98, 115, 89, 73, 111, 102, 0, //'2'
34, 99, 73, 73, 127, 54, 0, //'3'
24, 28, 22, 83, 127, 127, 80, //'4'
39, 103, 69, 69, 125, 57, 0, //'5'
60, 126, 75, 73, 121, 48, 0, //'6'
3, 3, 113, 121, 15, 7, 0, //'7'
54, 127, 73, 73, 127, 54, 0, //'8'
6, 79, 73, 105, 63, 30, 0, //'9'
0, 0, 102, 102, 0, 0, 0, //':'
0, 128, 230, 102, 0, 0, 0, //';'
8, 28, 54, 99, 65, 0, 0, //'<'
36, 36, 36, 36, 36, 36, 0, //'='
0, 65, 99, 54, 28, 8, 0, //'>'
2, 3, 81, 89, 15, 6, 0, //'?'
62, 127, 65, 93, 93, 31, 30, //'@'
124, 126, 19, 19, 126, 124, 0, //'A'
65, 127, 127, 73, 73, 127, 54, //'B'
28, 62, 99, 65, 65, 99, 34, //'C'
65, 127, 127, 65, 99, 62, 28, //'D'
65, 127, 127, 73, 93, 65, 99, //'E'
65, 127, 127, 73, 29, 1, 3, //'F'
28, 62, 99, 65, 81, 115, 114, //'G'
127, 127, 8, 8, 127, 127, 0, //'H'
0, 65, 127, 127, 65, 0, 0, //'I'
48, 112, 64, 65, 127, 63, 1, //'J'
65, 127, 127, 8, 28, 119, 99, //'K'
127, 127, 8, 8, 127, 127, 0, //'H'
0, 65, 127, 127, 65, 0, 0, //'I'
48, 112, 64, 65, 127, 63, 1, //'J'
65, 127, 127, 8, 28, 119, 99, //'K'
65, 127, 127, 65, 64, 96, 112, //'L'
127, 127, 14, 28, 14, 127, 127, //'M'
127, 127, 6, 12, 24, 127, 127, //'N'
28, 62, 99, 65, 99, 62, 28, //'O'
65, 127, 127, 73, 9, 15, 6, //'P'
30, 63, 33, 113, 127, 94, 0, //'Q'
28, 62, 99, 65, 99, 62, 28, //'O'
65, 127, 127, 73, 9, 15, 6, //'P'
30, 63, 33, 113, 127, 94, 0, //'Q'
65, 127, 127, 9, 25, 127, 102, //'R'
38, 111, 77, 89, 115, 50, 0, //'S'
3, 65, 127, 127, 65, 3, 0, //'T'
127, 127, 64, 64, 127, 127, 0, //'U'
31, 63, 96, 96, 63, 31, 0, //'V'
38, 111, 77, 89, 115, 50, 0, //'S'
3, 65, 127, 127, 65, 3, 0, //'T'
127, 127, 64, 64, 127, 127, 0, //'U'
31, 63, 96, 96, 63, 31, 0, //'V'
127, 127, 48, 24, 48, 127, 127, //'W'
67, 103, 60, 24, 60, 103, 67, //'X'
7, 79, 120, 120, 79, 7, 0, //'Y'
67, 103, 60, 24, 60, 103, 67, //'X'
7, 79, 120, 120, 79, 7, 0, //'Y'
71, 99, 113, 89, 77, 103, 115, //'Z'
0, 127, 127, 65, 65, 0, 0, //'['
1, 3, 6, 12, 24, 48, 96, //'\'
0, 65, 65, 127, 127, 0, 0, //']'
8, 12, 6, 3, 6, 12, 8, //'^'
0, 127, 127, 65, 65, 0, 0, //'['
1, 3, 6, 12, 24, 48, 96, //'\'
0, 65, 65, 127, 127, 0, 0, //']'
8, 12, 6, 3, 6, 12, 8, //'^'
128, 128, 128, 128, 128, 128, 128, //'_'
0, 0, 3, 7, 4, 0, 0, //'`'
32, 116, 84, 84, 60, 120, 64, //'a'
65, 127, 63, 72, 72, 120, 48, //'b'
56, 124, 68, 68, 108, 40, 0, //'c'
48, 120, 72, 73, 63, 127, 64, //'d'
56, 124, 84, 84, 92, 24, 0, //'e'
72, 126, 127, 73, 3, 2, 0, //'f'
56, 188, 164, 164, 252, 120, 0, //'g'
0, 0, 3, 7, 4, 0, 0, //'`'
32, 116, 84, 84, 60, 120, 64, //'a'
65, 127, 63, 72, 72, 120, 48, //'b'
56, 124, 68, 68, 108, 40, 0, //'c'
48, 120, 72, 73, 63, 127, 64, //'d'
56, 124, 84, 84, 92, 24, 0, //'e'
72, 126, 127, 73, 3, 2, 0, //'f'
56, 188, 164, 164, 252, 120, 0, //'g'
65, 127, 127, 8, 4, 124, 120, //'h'
0, 68, 125, 125, 64, 0, 0, //'i'
96, 224, 128, 128, 253, 125, 0, //'j'
65, 127, 127, 16, 56, 108, 68, //'k'
0, 65, 127, 127, 64, 0, 0, //'l'
0, 68, 125, 125, 64, 0, 0, //'i'
96, 224, 128, 128, 253, 125, 0, //'j'
65, 127, 127, 16, 56, 108, 68, //'k'
0, 65, 127, 127, 64, 0, 0, //'l'
120, 124, 28, 56, 28, 124, 120, //'m'
124, 124, 4, 4, 124, 120, 0, //'n'
56, 124, 68, 68, 124, 56, 0, //'o'
0, 252, 252, 164, 36, 60, 24, //'p'
124, 124, 4, 4, 124, 120, 0, //'n'
56, 124, 68, 68, 124, 56, 0, //'o'
0, 252, 252, 164, 36, 60, 24, //'p'
24, 60, 36, 164, 248, 252, 132, //'q'
68, 124, 120, 76, 4, 28, 24, //'r'
72, 92, 84, 84, 116, 36, 0, //'s'
0, 4, 62, 127, 68, 36, 0, //'t'
60, 124, 64, 64, 60, 124, 64, //'u'
28, 60, 96, 96, 60, 28, 0, //'v'
60, 124, 112, 56, 112, 124, 60, //'w'
68, 108, 56, 16, 56, 108, 68, //'x'
60, 188, 160, 160, 252, 124, 0, //'y'
76, 100, 116, 92, 76, 100, 0, //'z'
8, 8, 62, 119, 65, 65, 0, //'{'
0, 0, 0, 119, 119, 0, 0, //'|'
65, 65, 119, 62, 8, 8, 0, //'}'
2, 3, 1, 3, 2, 3, 1, //'~'
68, 124, 120, 76, 4, 28, 24, //'r'
72, 92, 84, 84, 116, 36, 0, //'s'
0, 4, 62, 127, 68, 36, 0, //'t'
60, 124, 64, 64, 60, 124, 64, //'u'
28, 60, 96, 96, 60, 28, 0, //'v'
60, 124, 112, 56, 112, 124, 60, //'w'
68, 108, 56, 16, 56, 108, 68, //'x'
60, 188, 160, 160, 252, 124, 0, //'y'
76, 100, 116, 92, 76, 100, 0, //'z'
8, 8, 62, 119, 65, 65, 0, //'{'
0, 0, 0, 119, 119, 0, 0, //'|'
65, 65, 119, 62, 8, 8, 0, //'}'
2, 3, 1, 3, 2, 3, 1, //'~'
255, 129, 129, 129, 129, 129, 255, //'^?'
14, 159, 145, 177, 251, 74, 0 //'?'
14, 159, 145, 177, 251, 74, 0 //'?'
};
/* Global variables */
const struct FONT_DEF Font_7x8 = { 7, 8, 32, 128, au8Font7x8, NULL, NULL };
const struct FONT_DEF Font_7x8 = {7, 8, 32, 128, au8Font7x8, NULL, NULL};

View File

@ -3294,122 +3294,122 @@ const uint8_t Ubuntu18ptBitmaps[] = {
/* Character descriptors */
const FONT_CHAR_INFO Ubuntu18ptLengths[] = {
{ 2 }, /* */
{ 5 }, /* ! */
{ 7 }, /* " */
{ 38 }, /* # */
{ 26 }, /* $ */
{ 45 }, /* % */
{ 37 }, /* & */
{ 4 }, /* ' */
{ 13 }, /* ( */
{ 12 }, /* ) */
{ 20 }, /* * */
{ 9 }, /* + */
{ 6 }, /* , */
{ 5 }, /* - */
{ 5 }, /* . */
{ 15 }, /* / */
{ 20 }, /* 0 */
{ 10 }, /* 1 */
{ 30 }, /* 2 */
{ 25 }, /* 3 */
{ 24 }, /* 4 */
{ 24 }, /* 5 */
{ 29 }, /* 6 */
{ 21 }, /* 7 */
{ 33 }, /* 8 */
{ 29 }, /* 9 */
{ 6 }, /* : */
{ 8 }, /* ; */
{ 23 }, /* < */
{ 6 }, /* = */
{ 23 }, /* > */
{ 19 }, /* ? */
{ 46 }, /* @ */
{ 29 }, /* A */
{ 21 }, /* B */
{ 21 }, /* C */
{ 18 }, /* D */
{ 10 }, /* E */
{ 10 }, /* F */
{ 21 }, /* G */
{ 10 }, /* H */
{ 5 }, /* I */
{ 13 }, /* J */
{ 28 }, /* K */
{ 7 }, /* L */
{ 28 }, /* M */
{ 22 }, /* N */
{ 28 }, /* O */
{ 19 }, /* P */
{ 40 }, /* Q */
{ 22 }, /* R */
{ 31 }, /* S */
{ 9 }, /* T */
{ 18 }, /* U */
{ 25 }, /* V */
{ 34 }, /* W */
{ 33 }, /* X */
{ 21 }, /* Y */
{ 33 }, /* Z */
{ 8 }, /* [ */
{ 16 }, /* \ */
{ 7 }, /* ] */
{ 19 }, /* ^ */
{ 5 }, /* _ */
{ 10 }, /* ` */
{ 21 }, /* a */
{ 18 }, /* b */
{ 14 }, /* c */
{ 19 }, /* d */
{ 28 }, /* e */
{ 13 }, /* f */
{ 21 }, /* g */
{ 12 }, /* h */
{ 6 }, /* i */
{ 10 }, /* j */
{ 23 }, /* k */
{ 8 }, /* l */
{ 19 }, /* m */
{ 12 }, /* n */
{ 22 }, /* o */
{ 19 }, /* p */
{ 18 }, /* q */
{ 8 }, /* r */
{ 29 }, /* s */
{ 11 }, /* t */
{ 13 }, /* u */
{ 18 }, /* v */
{ 29 }, /* w */
{ 28 }, /* x */
{ 21 }, /* y */
{ 28 }, /* z */
{ 15 }, /* { */
{ 5 }, /* | */
{ 14 }, /* } */
{ 17 }, /* ~ */
{ 32 }, /* Ä */
{ 39 }, /* Ö */
{ 26 }, /* Ü */
{ 31 }, /* ß */
{ 30 }, /* ä */
{ 29 }, /* ö */
{ 19 }, /* ü */
{ 30 }, /* € */
{2}, /* */
{5}, /* ! */
{7}, /* " */
{38}, /* # */
{26}, /* $ */
{45}, /* % */
{37}, /* & */
{4}, /* ' */
{13}, /* ( */
{12}, /* ) */
{20}, /* * */
{9}, /* + */
{6}, /* , */
{5}, /* - */
{5}, /* . */
{15}, /* / */
{20}, /* 0 */
{10}, /* 1 */
{30}, /* 2 */
{25}, /* 3 */
{24}, /* 4 */
{24}, /* 5 */
{29}, /* 6 */
{21}, /* 7 */
{33}, /* 8 */
{29}, /* 9 */
{6}, /* : */
{8}, /* ; */
{23}, /* < */
{6}, /* = */
{23}, /* > */
{19}, /* ? */
{46}, /* @ */
{29}, /* A */
{21}, /* B */
{21}, /* C */
{18}, /* D */
{10}, /* E */
{10}, /* F */
{21}, /* G */
{10}, /* H */
{5}, /* I */
{13}, /* J */
{28}, /* K */
{7}, /* L */
{28}, /* M */
{22}, /* N */
{28}, /* O */
{19}, /* P */
{40}, /* Q */
{22}, /* R */
{31}, /* S */
{9}, /* T */
{18}, /* U */
{25}, /* V */
{34}, /* W */
{33}, /* X */
{21}, /* Y */
{33}, /* Z */
{8}, /* [ */
{16}, /* \ */
{7}, /* ] */
{19}, /* ^ */
{5}, /* _ */
{10}, /* ` */
{21}, /* a */
{18}, /* b */
{14}, /* c */
{19}, /* d */
{28}, /* e */
{13}, /* f */
{21}, /* g */
{12}, /* h */
{6}, /* i */
{10}, /* j */
{23}, /* k */
{8}, /* l */
{19}, /* m */
{12}, /* n */
{22}, /* o */
{19}, /* p */
{18}, /* q */
{8}, /* r */
{29}, /* s */
{11}, /* t */
{13}, /* u */
{18}, /* v */
{29}, /* w */
{28}, /* x */
{21}, /* y */
{28}, /* z */
{15}, /* { */
{5}, /* | */
{14}, /* } */
{17}, /* ~ */
{32}, /* Ä */
{39}, /* Ö */
{26}, /* Ü */
{31}, /* ß */
{30}, /* ä */
{29}, /* ö */
{19}, /* ü */
{30}, /* € */
};
const uint16_t Ubuntu18ptExtra[] = { 196, 214, 220, 223, 228,
246, 252, 8364, 65535 };
const uint16_t Ubuntu18ptExtra[] = {196, 214, 220, 223, 228, 246, 252, 8364, 65535};
/* Font info */
const struct FONT_DEF Font_Ubuntu18pt = { 1, /* width (1 == comressed) */
26, /* character height */
32, /* first char */
126, /* last char */
Ubuntu18ptBitmaps,
Ubuntu18ptLengths,
Ubuntu18ptExtra };
const struct FONT_DEF Font_Ubuntu18pt = {
1, /* width (1 == comressed) */
26, /* character height */
32, /* first char */
126, /* last char */
Ubuntu18ptBitmaps,
Ubuntu18ptLengths,
Ubuntu18ptExtra};
/* Font metadata:
* Name: Ubuntu Regular 18pt

View File

@ -34,47 +34,49 @@
#include <sgpio.h>
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
/*
* RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on
* the RFFC5072.
*
* On HackRF One, the same signals are controlled by GPIO on the LPC.
* SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used
* on HackRF One as the amplifier power is instead controlled only by
* SWITCHCTRL_AMP_BYPASS.
*
* The rad1o also uses GPIO pins to control the different switches. The amplifiers
* are also connected to the LPC.
*/
#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */
#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */
#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */
#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */
#define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */
#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */
/*
* RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on
* the RFFC5072.
*
* On HackRF One, the same signals are controlled by GPIO on the LPC.
* SWITCHCTRL_NO_TX_AMP_PWR and SWITCHCTRL_NO_RX_AMP_PWR are not normally used
* on HackRF One as the amplifier power is instead controlled only by
* SWITCHCTRL_AMP_BYPASS.
*
* The rad1o also uses GPIO pins to control the different switches. The amplifiers
* are also connected to the LPC.
*/
#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */
#define SWITCHCTRL_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */
#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */
#define SWITCHCTRL_MIX_BYPASS (1 << 3) /* GPO4 bypass RFFC5072 mixer section */
#define SWITCHCTRL_HP (1 << 4) /* GPO5 1 for high-pass, 0 for low-pass */
#define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */
/*
GPO6 GPO5 GPO4 GPO3 GPO2 GPO1
!RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode
1 X 1 1 1 1 TX bypass Bypass
1 X 1 1 0 0 TX bypass TX amplified
1 1 0 1 1 1 TX high Bypass
1 1 0 1 0 0 TX high TX amplified
1 0 0 1 1 1 TX low Bypass
1 0 0 1 0 0 TX low TX amplified
1 X 1 0 1 1 RX bypass Bypass
0 X 1 0 0 1 RX bypass RX amplified
1 1 0 0 1 1 RX high Bypass
0 1 0 0 0 1 RX high RX amplified
1 0 0 0 1 1 RX low Bypass
0 0 0 0 0 1 RX low RX amplified
*/
/*
GPO6 GPO5 GPO4 GPO3 GPO2 GPO1
!RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode
1 X 1 1 1 1 TX bypass Bypass
1 X 1 1 0 0 TX bypass TX amplified
1 1 0 1 1 1 TX high Bypass
1 1 0 1 0 0 TX high TX amplified
1 0 0 1 1 1 TX low Bypass
1 0 0 1 0 0 TX low TX amplified
1 X 1 0 1 1 RX bypass Bypass
0 X 1 0 0 1 RX bypass RX amplified
1 1 0 0 1 1 RX high Bypass
0 1 0 0 0 1 RX high RX amplified
1 0 0 0 1 1 RX low Bypass
0 0 0 0 0 1 RX low RX amplified
*/
/*
* Safe (initial) switch settings turn off both amplifiers and enable both amp
* 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)
/*
* Safe (initial) switch settings turn off both amplifiers and enable both amp
* 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)
#endif
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 */
#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) {
gpio_set(rf_path->gpio_tx);
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
* 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);
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR)
}
if (ctrl & SWITCHCTRL_NO_RX_AMP_PWR) {
gpio_set(rf_path->gpio_no_rx_amp_pwr);
}
if (ctrl & SWITCHCTRL_ANT_PWR) {
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
#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) {
gpio_set(rf_path->gpio_tx_rx_n);
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
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
(void) rf_path; /* silence unused param warning */
mixer_set_gpo(&mixer, gpo);
@ -233,29 +240,32 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) {
#elif RAD1O
switchctrl_set_rad1o(rf_path, gpo);
#else
(void)gpo;
(void) gpo;
#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
/* Configure RF switch control signals */
scu_pinmux(SCU_HP, 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_NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_NO_TX_AMP_PWR, 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_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
// clang-format off
scu_pinmux(SCU_HP, 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_NO_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_RX_MIX_BP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_AMP, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_MIX_BYPASS, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
scu_pinmux(SCU_NO_TX_AMP_PWR, 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_NO_RX_AMP_PWR, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
// clang-format on
/* 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);
/* Configure RF switch control signals as outputs */
gpio_output(rf_path->gpio_amp_bypass);
@ -279,20 +289,22 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
switchctrl_set(rf_path, SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_MIX_BYPASS);
#elif RAD1O
/* Configure RF switch control signals */
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_TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LOW_HIGH_FILT_N,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_MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
// clang-format off
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_TX_RX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_TX_RX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_MIX, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_BY_MIX_N, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LOW_HIGH_FILT, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_LOW_HIGH_FILT_N, 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_MIXER_EN, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
// clang-format on
/* 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);
/* Configure RF switch control signals as outputs */
gpio_output(rf_path->gpio_tx_rx_n);
@ -317,31 +329,33 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
#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();
max5864_setup(&max5864);
max5864_shutdown(&max5864);
ssp1_set_mode_max2837();
max2837_setup(&max2837);
max2837_start(&max2837);
mixer_setup(&mixer);
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. */
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
switch(direction) {
switch (direction) {
case RF_PATH_DIRECTION_TX:
rf_path->switchctrl |= SWITCHCTRL_TX;
if( (rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
if ((rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0) {
/* TX amplifier is in path, be sure to enable TX amplifier. */
rf_path->switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR;
}
mixer_tx(&mixer);
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) {
if (rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS) {
mixer_disable(&mixer);
} else {
mixer_enable(&mixer);
@ -352,15 +366,15 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
max2837_tx(&max2837);
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX);
break;
case RF_PATH_DIRECTION_RX:
rf_path->switchctrl &= ~SWITCHCTRL_TX;
if( (rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0 ) {
if ((rf_path->switchctrl & SWITCHCTRL_AMP_BYPASS) == 0) {
/* RX amplifier is in path, be sure to enable RX amplifier. */
rf_path->switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR;
}
mixer_rx(&mixer);
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) {
if (rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS) {
mixer_disable(&mixer);
} else {
mixer_enable(&mixer);
@ -371,7 +385,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
max2837_rx(&max2837);
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX);
break;
case RF_PATH_DIRECTION_OFF:
default:
#ifdef HACKRF_ONE
@ -394,19 +408,20 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
hackrf_ui()->set_direction(direction);
}
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) {
switch(filter) {
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
{
switch (filter) {
default:
case RF_PATH_FILTER_BYPASS:
rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS;
mixer_disable(&mixer);
break;
case RF_PATH_FILTER_LOW_PASS:
rf_path->switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
mixer_enable(&mixer);
break;
case RF_PATH_FILTER_HIGH_PASS:
rf_path->switchctrl &= ~SWITCHCTRL_MIX_BYPASS;
rf_path->switchctrl |= SWITCHCTRL_HP;
@ -419,29 +434,34 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
hackrf_ui()->set_filter(filter);
}
void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) {
if( enable ) {
if( rf_path->switchctrl & SWITCHCTRL_TX ) {
void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable)
{
if (enable) {
if (rf_path->switchctrl & SWITCHCTRL_TX) {
/* 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_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
rf_path->switchctrl &=
~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
} else {
/* 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_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
rf_path->switchctrl &=
~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
}
} else {
/* 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);
hackrf_ui()->set_lna_power(enable);
}
/* 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) {
rf_path->switchctrl |= SWITCHCTRL_ANT_PWR;
} else {

View File

@ -81,4 +81,4 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
void rf_path_set_lna(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);
#endif/*__RFPATH_H__*/
#endif /*__RFPATH_H__*/

View File

@ -39,38 +39,39 @@
#include "hackrf_core.h"
/* Default register values. */
static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
0xbefa, /* 00 */
0x4064, /* 01 */
0x9055, /* 02 */
0x2d02, /* 03 */
0xacbf, /* 04 */
0xacbf, /* 05 */
0x0028, /* 06 */
0x0028, /* 07 */
0xff00, /* 08 */
0x8220, /* 09 */
0x0202, /* 0A */
0x4800, /* 0B */
0x1a94, /* 0C */
0xd89d, /* 0D */
0x8900, /* 0E */
0x1e84, /* 0F */
0x89d8, /* 10 */
0x9d00, /* 11 */
0x2a20, /* 12 */
0x0000, /* 13 */
0x0000, /* 14 */
0x0000, /* 15 */
0x0000, /* 16 */
0x4900, /* 17 */
0x0281, /* 18 */
0xf00f, /* 19 */
0x0000, /* 1A */
0x0000, /* 1B */
0xc840, /* 1C */
0x1000, /* 1D */
0x0005, /* 1E */ };
static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
0xbefa, /* 00 */
0x4064, /* 01 */
0x9055, /* 02 */
0x2d02, /* 03 */
0xacbf, /* 04 */
0xacbf, /* 05 */
0x0028, /* 06 */
0x0028, /* 07 */
0xff00, /* 08 */
0x8220, /* 09 */
0x0202, /* 0A */
0x4800, /* 0B */
0x1a94, /* 0C */
0xd89d, /* 0D */
0x8900, /* 0E */
0x1e84, /* 0F */
0x89d8, /* 10 */
0x9d00, /* 11 */
0x2a20, /* 12 */
0x0000, /* 13 */
0x0000, /* 14 */
0x0000, /* 15 */
0x0000, /* 16 */
0x4900, /* 17 */
0x0281, /* 18 */
0xf00f, /* 19 */
0x0000, /* 1A */
0x0000, /* 1B */
0xc840, /* 1C */
0x1000, /* 1D */
0x0005,
/* 1E */};
/* Set up all registers according to defaults specified in docs. */
void rffc5071_init(rffc5071_driver_t* const drv)
@ -120,26 +121,29 @@ void rffc5071_setup(rffc5071_driver_t* const drv)
rffc5071_regs_commit(drv);
}
static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) {
(void)drv;
static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r)
{
(void) drv;
uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff };
uint16_t data[] = {0x80 | (r & 0x7f), 0xffff};
spi_bus_transfer(drv->bus, data, 2);
return data[1];
}
static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) {
(void)drv;
static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v)
{
(void) drv;
uint16_t data[] = { 0x00 | (r & 0x7f), v };
uint16_t data[] = {0x00 | (r & 0x7f), v};
spi_bus_transfer(drv->bus, data, 2);
}
uint16_t rffc5071_reg_read(rffc5071_driver_t* const drv, uint8_t r)
{
/* Readback register is not cached. */
if (r == RFFC5071_READBACK_REG)
if (r == RFFC5071_READBACK_REG) {
return rffc5071_spi_read(drv, r);
}
/* Discard uncommited write when reading. This shouldn't
* happen, and probably has not been tested. */
@ -164,21 +168,23 @@ static inline void rffc5071_reg_commit(rffc5071_driver_t* const drv, uint8_t r)
void rffc5071_regs_commit(rffc5071_driver_t* const drv)
{
int r;
for(r = 0; r < RFFC5071_NUM_REGS; r++) {
for (r = 0; r < RFFC5071_NUM_REGS; r++) {
if ((drv->regs_dirty >> r) & 0x1) {
rffc5071_reg_commit(drv, r);
}
}
}
void rffc5071_tx(rffc5071_driver_t* const drv) {
void rffc5071_tx(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 0);
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
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_FULLD(drv, 0);
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
* 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_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */
rffc5071_regs_commit(drv);
@ -197,22 +204,25 @@ void rffc5071_rxtx(rffc5071_driver_t* const 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);
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);
rffc5071_regs_commit(drv);
}
#define LO_MAX 5400
#define REF_FREQ 40
#define FREQ_ONE_MHZ (1000*1000)
#define LO_MAX 5400
#define REF_FREQ 40
#define FREQ_ONE_MHZ (1000 * 1000)
/* 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;
uint16_t fvco;
uint8_t fbkdiv;
@ -220,7 +230,7 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
uint64_t tune_freq_hz;
uint16_t p1nmsb;
uint8_t p1nlsb;
/* Calculate n_lo */
uint8_t n_lo = 0;
uint16_t x = LO_MAX / lo;
@ -245,14 +255,14 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
set_RFFC5071_PLLCPL(drv, 2);
}
uint64_t tmp_n = ((uint64_t)fvco << 29ULL) / (fbkdiv*REF_FREQ) ;
uint64_t tmp_n = ((uint64_t) fvco << 29ULL) / (fbkdiv * REF_FREQ);
n = tmp_n >> 29ULL;
p1nmsb = (tmp_n >> 13ULL) & 0xffff;
p1nlsb = (tmp_n >> 5ULL) & 0xff;
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ)
/ (lodiv * (1 << 24ULL));
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ) /
(lodiv * (1 << 24ULL));
/* Path 2 */
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 !!!!!!!!!!! */
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;
rffc5071_disable(drv);

View File

@ -25,37 +25,44 @@
#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;
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;
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;
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;
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;
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;
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;
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);
}
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;
/* Configure GPIO pins. */
@ -82,22 +90,26 @@ static void rffc5071_spi_target_init(spi_bus_t* const 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;
rffc5071_spi_bus_init(bus);
rffc5071_spi_target_init(bus);
}
void rffc5071_spi_stop(spi_bus_t* const bus) {
(void)bus;
void rffc5071_spi_stop(spi_bus_t* const bus)
{
(void) bus;
}
static void rffc5071_spi_serial_delay(spi_bus_t* const bus) {
(void)bus;
static void rffc5071_spi_serial_delay(spi_bus_t* const bus)
{
(void) bus;
__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;
rffc5071_spi_serial_delay(bus);
@ -107,13 +119,18 @@ static void rffc5071_spi_sck(spi_bus_t* const bus) {
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_sck(bus);
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;
const uint32_t msb = 1UL << (count - 1);
uint32_t t = data;
@ -141,13 +158,14 @@ static uint32_t rffc5071_spi_exchange_word(spi_bus_t* const bus, const uint32_t
* next 7 bits are register address,
* next 16 bits are register value.
*/
void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t count) {
if( count != 2 ) {
void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t count)
{
if (count != 2) {
return;
}
uint16_t* const data = _data;
const bool direction_read = (data[0] >> 7) & 1;
/*
@ -160,7 +178,7 @@ void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t
rffc5071_spi_target_select(bus);
data[0] = rffc5071_spi_exchange_word(bus, data[0], 9);
if( direction_read ) {
if (direction_read) {
rffc5071_spi_direction_in(bus);
rffc5071_spi_sck(bus);
}
@ -177,8 +195,12 @@ void rffc5071_spi_transfer(spi_bus_t* const bus, void* const _data, const size_t
rffc5071_spi_sck(bus);
}
void rffc5071_spi_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfer, const size_t count) {
if( count == 1 ) {
void rffc5071_spi_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfer,
const size_t count)
{
if (count == 1) {
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_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_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

View File

@ -19,24 +19,25 @@
* Boston, MA 02110-1301, USA.
*/
#include "hackrf_core.h"
#include "hackrf_core.h"
#include <stdint.h>
#include "rom_iap.h"
#include "w25q80bv.h"
#define ROM_IAP_ADDR (0x10400100)
#define ROM_IAP_ADDR (0x10400100)
#define ROM_IAP_UNDEF_ADDR (0x12345678)
#define ROM_OTP_PART_ID_ADDR (0x40045000)
typedef void (* IAP_t)(uint32_t [],uint32_t[]);
typedef void (*IAP_t)(uint32_t[], uint32_t[]);
typedef struct {
const IAP_t IAP; /* If equal to 0x12345678 IAP not implemented */
/* Other TBD */
} *pENTRY_ROM_API_t;
#define pROM_API ((pENTRY_ROM_API_t)ROM_IAP_ADDR)
typedef struct {
const IAP_t IAP; /* If equal to 0x12345678 IAP not implemented */
/* Other TBD */
} * pENTRY_ROM_API_t;
#define pROM_API ((pENTRY_ROM_API_t) ROM_IAP_ADDR)
/*
See Errata sheet ES_LPC43X0_A.pdf (LPC4350/30/20/10 Rev A)
@ -54,25 +55,23 @@ typedef struct {
bool iap_is_implemented(void)
{
bool res;
if( *((uint32_t*)ROM_IAP_ADDR) != ROM_IAP_UNDEF_ADDR )
{
if (*((uint32_t*) ROM_IAP_ADDR) != ROM_IAP_UNDEF_ADDR) {
res = true;
}else
{
} else {
res = false;
}
return res;
}
isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
{
uint32_t* p_u32_data;
if( iap_is_implemented() )
{
pROM_API->IAP( (uint32_t*)&iap_cmd_res->cmd_param, (uint32_t*)&iap_cmd_res->status_res);
}else
{
if (iap_is_implemented()) {
pROM_API->IAP(
(uint32_t*) &iap_cmd_res->cmd_param,
(uint32_t*) &iap_cmd_res->status_res);
} else {
/*
Alternative way to retrieve Part Id on MCU with no IAP
Read Serial No => Read Unique ID in SPIFI (only compatible with W25Q80BV
@ -80,25 +79,27 @@ isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res)
spi_bus_start(spi_flash.bus, &ssp_config_w25q80bv);
w25q80bv_setup(&spi_flash);
switch(iap_cmd_res->cmd_param.command_code)
{
case IAP_CMD_READ_PART_ID_NO:
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[1] = p_u32_data[1];
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
switch (iap_cmd_res->cmd_param.command_code) {
case IAP_CMD_READ_PART_ID_NO:
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[1] = p_u32_data[1];
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
break;
case IAP_CMD_READ_SERIAL_NO:
case IAP_CMD_READ_SERIAL_NO:
/* Only 64bits used */
iap_cmd_res->status_res.iap_result[0] = 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] );
iap_cmd_res->status_res.status_ret = CMD_SUCCESS;
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;
break;
default:
iap_cmd_res->status_res.status_ret = ERROR_IAP_NOT_IMPLEMENTED;
default:
iap_cmd_res->status_res.status_ret = ERROR_IAP_NOT_IMPLEMENTED;
break;
}
}

View File

@ -23,92 +23,92 @@
#define __ROM_IAP__
#include <stdint.h>
#include <stdbool.h>
typedef enum
{
typedef enum {
/* TODO define other commands */
IAP_CMD_INIT_IAP = 49,
/* Command Init IAP
Input Command code: 49 (decimal)
Return Code CMD_SUCCESS
Result None
Input: Command code: 49 (decimal)
Return Code: CMD_SUCCESS
Result: None
Description Initializes and prepares the flash for erase and write operations.
Stack usage 88 B */
IAP_CMD_READ_PART_ID_NO = 54,
IAP_CMD_READ_PART_ID_NO = 54,
/* Read part identification number
Command Read part identification number
Input Command code: 54 (decimal)
Parameters:None
Return Code CMD_SUCCESS |
Result Result0:Part Identification Number.
Result1:Part Identification Number.
Description This command is used to read the part identification number. See Table 1082
LPC43xx part identification numbers.
The command returns two words: word0 followed by word1. Word 0 corresponds
to the part id and word1 indicates the flash configuration or contains 0x0 for
flashless parts.
Stack usage 8 B */
Input: Command code: 54 (decimal)
Parameters:None
Return Code: CMD_SUCCESS
Result Result0:Part Identification Number.
Result1:Part Identification Number.
Description: This command is used to read the part identification number. See Table 1082
'LPC43xx part identification numbers'. The command returns two words: word0
followed by word1. Word 0 corresponds to the part id and word1 indicates the flash
configuration or contains 0x0 for flashless parts.
Stack usage: 8 B */
IAP_CMD_READ_SERIAL_NO = 58
/* Read device serial number
Input Command code: 58 (decimal)
Parameters: None
Return Code CMD_SUCCESS
Result Result0:First 32-bit word of Device Identification Number (at the lowest address)
Result1:Second 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
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.
Stack usage 8 B */
Input: Command code: 58 (decimal)
Parameters: None
Return Code: CMD_SUCCESS
Result: Result0: First 32-bit word of Device Identification Number (at the lowest address)
Result1: Second 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
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.
Stack usage: 8 B */
} iap_cmd_code_t;
/* ISP/IAP Return Code */
// clang-format off
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. */
INVALID_COMMAND = 0x00000001, /* Invalid command. */
SRC_ADDR_ERROR = 0x00000002, /* Source address is not on word boundary. */
DST_ADDR_ERROR = 0x00000003, /* Destination address not on word or 256 byte boundary. */
SRC_ADDR_NOT_MAPPED = 0x00000004, /* Source address is not mapped in the memory map. Count value is taken into consideration where applicable. */
DST_ADDR_NOT_MAPPED = 0x00000005, /* Destination address is not mapped in the memory map. Count value is taken into consideration where applicable.*/
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. */
SRC_ADDR_ERROR = 0x00000002, /* Source address is not on word boundary. */
DST_ADDR_ERROR = 0x00000003, /* Destination address not on word or 256 byte boundary. */
SRC_ADDR_NOT_MAPPED = 0x00000004, /* Source address is not mapped in the memory map. Count value is taken into consideration where applicable. */
DST_ADDR_NOT_MAPPED = 0x00000005, /* Destination address is not mapped in the memory map. Count value is taken into consideration where applicable.*/
COUNT_ERROR = 0x00000006, /* Byte count is not multiple of 4 or is not a permitted value. */
INVALID_SECTOR = 0x00000007, /* Sector number is invalid or end sector number is greater than start sector number. */
SECTOR_NOT_BLANK = 0x00000008, /* Sector is not blank. */
SECTOR_NOT_PREP_WRITE_OP = 0x00000009, /* Command to prepare sector for write operation was not executed. */
COMPARE_ERROR = 0x0000000A, /* Source and destination data not equal. */
BUSY = 0x0000000B, /* Flash programming hardware interface is busy. */
BUSY = 0x0000000B, /* Flash programming hardware interface is busy. */
PARAM_ERROR = 0x0000000C, /* Insufficient number of parameters or invalid parameter. */
ADDR_ERROR = 0x0000000D, /* Address is not on word boundary. */
ADDR_NOT_MAPPED = 0x0000000E, /* Address is not mapped in the memory map. Count value is taken in to consideration where applicable. */
ADDR_NOT_MAPPED = 0x0000000E, /* Address is not mapped in the memory map. Count value is taken in to consideration where applicable. */
CMD_LOCKED = 0x0000000F, /* Command is locked. */
INVALID_CODE = 0x00000010, /* Unlock code is invalid. */
INVALID_BAUD_RATE = 0x00000011, /* Invalid baud rate setting. */
INVALID_STOP_BIT = 0x00000012, /* Invalid stop bit setting. */
INVALID_BAUD_RATE = 0x00000011, /* Invalid baud rate setting. */
INVALID_STOP_BIT = 0x00000012, /* Invalid stop bit setting. */
CODE_READ_PROTECTION_ENABLED = 0x00000013, /* Code read protection enabled. */
INVALID_FLASH_UNIT = 0x00000014, /* Invalid flash unit. */
USER_CODE_CHECKSUM = 0x00000015,
INVALID_FLASH_UNIT = 0x00000014, /* Invalid flash unit. */
USER_CODE_CHECKSUM = 0x00000015,
ERROR_SETTING_ACTIVE_PARTITION = 0x00000016,
/* Special Error */
ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */
} isp_iap_ret_code_t;
typedef struct
{
// clang-format on
typedef struct {
/* Input Command/Param */
struct
{
struct {
iap_cmd_code_t command_code;
uint32_t iap_param[5];
} cmd_param;
/* Output Status/Result */
struct
{
isp_iap_ret_code_t status_ret;
struct {
isp_iap_ret_code_t status_ret;
uint32_t iap_result[4];
} status_res;
} iap_cmd_res_t;
@ -118,4 +118,4 @@ bool iap_is_implemented(void);
isp_iap_ret_code_t iap_cmd_call(iap_cmd_res_t* iap_cmd_res);
#endif//__ROM_IAP__
#endif //__ROM_IAP__

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);
#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_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
@ -46,50 +47,69 @@ void sgpio_configure_pin_functions(sgpio_config_t* const config) {
scu_pinmux(SCU_PINMUX_SGPIO10, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
scu_pinmux(SCU_PINMUX_SGPIO11, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
scu_pinmux(SCU_PINMUX_SGPIO12, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); /* GPIO0[13] */
scu_pinmux(SCU_PINMUX_SGPIO13, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */
scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[13] */
scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */
scu_pinmux(SCU_PINMUX_SGPIO13, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[12] */
scu_pinmux(SCU_PINMUX_SGPIO14, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[13] */
scu_pinmux(SCU_PINMUX_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */
sgpio_cpld_stream_rx_set_q_invert(config, 0);
hw_sync_enable(0);
hw_sync_enable(0);
gpio_output(config->gpio_rx_q_invert);
gpio_output(config->gpio_hw_sync_enable);
}
void sgpio_set_slice_mode(
sgpio_config_t* const config,
const bool multi_slice
) {
void sgpio_set_slice_mode(sgpio_config_t* const config, const bool 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)
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 ...)
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
SGPIO 0 to 7 = DAC/ADC data bits 0 to 7
(Note: DAC is 10 bits but only bit 9 to bit 2 are used, bits 1 & 0 are forced to 0 by CPLD)
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 ...)
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)
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)
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
*/
void sgpio_configure(
sgpio_config_t* const config,
const sgpio_direction_t direction
) {
void sgpio_configure(sgpio_config_t* const config, const sgpio_direction_t direction)
{
// Disable all counters during configuration
SGPIO_CTRL_ENABLE = 0;
// Set SGPIO output values.
const uint_fast8_t cpld_direction =
(direction == SGPIO_DIRECTION_TX) ? 1 : 0;
SGPIO_GPIO_OUTREG =
(cpld_direction << 11) /* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode)*/
| (1L << 10) // disable codec data stream during configuration (Output SGPIO10 High)
// Set SGPIO output values.
const uint_fast8_t cpld_direction = (direction == SGPIO_DIRECTION_TX) ? 1 : 0;
// clang-format off
SGPIO_GPIO_OUTREG =
(cpld_direction << 11) // 1 = Output SGPIO11 High (TX mode)
// 0 = Output SGPIO11 Low (RX mode)
| (1L << 10) // disable codec data stream during configuration
// (Output SGPIO10 High)
;
// clang-format on
#ifdef RAD1O
/* The data direction might have changed. Check if we need to
@ -99,48 +119,49 @@ void sgpio_configure(
// Enable SGPIO pin outputs.
const uint_fast16_t sgpio_gpio_data_direction =
(direction == SGPIO_DIRECTION_TX)
? (0xFF << 0)
: (0x00 << 0);
SGPIO_GPIO_OENREG =
(1L << 14) // GPDMA burst request SGPIO14 active
| (1L << 11) // direction output SGPIO11 active
| (1L << 10) // disable output SGPIO10 active
| (0L << 9) // capture input SGPIO9 (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)
;
(direction == SGPIO_DIRECTION_TX) ? (0xFF << 0) : (0x00 << 0);
SGPIO_OUT_MUX_CFG( 8) = // SGPIO8: Input: clock
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) /* 0x0 gpio_oe (state set by GPIO_OEREG) */
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */
// clang-format off
SGPIO_GPIO_OENREG =
(1L << 14) // GPDMA burst request SGPIO14 active
| (1L << 11) // direction output SGPIO11 active
| (1L << 10) // disable output SGPIO10 active
| (0L << 9) // capture input SGPIO9 (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_OUT_MUX_CFG( 8) = // SGPIO8:
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| 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_P_OE_CFG(0) /* 0x0 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( 9) = // SGPIO9: Input: qualifier
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| 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_P_OE_CFG(0) /* 0x0 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(10) = // GPIO10: Output: disable
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| 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_P_OE_CFG(0) /* 0x0 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(11) = // GPIO11: Output: direction
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // gpio_oe (state set by GPIO_OEREG)
| 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_P_OE_CFG(0) /* 0x4 dout_oem1 (1-bit mode) */
| SGPIO_OUT_MUX_CFG_P_OUT_CFG(0) /* 0x0 dout_doutm1 (1-bit mode) */
SGPIO_OUT_MUX_CFG(14) = // SGPIO14: Output: internal GPDMA burst request
SGPIO_OUT_MUX_CFG_P_OE_CFG(0) // dout_oem1 (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 =
config->slice_mode_multislice ? 11 : 9;
/* 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_OUT_MUX_CFG(i) =
SGPIO_OUT_MUX_CFG_P_OE_CFG(0)
| 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) */
;
SGPIO_OUT_MUX_CFG(i) = SGPIO_OUT_MUX_CFG_P_OE_CFG(0)
// 11 = dout_doutm8c (8-bit mode 8c) (multislice L0/7, N0/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[] = {
@ -154,87 +175,87 @@ void sgpio_configure(
SGPIO_SLICE_L,
};
const uint_fast8_t slice_gpdma = SGPIO_SLICE_H;
const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03;
const bool single_slice = !config->slice_mode_multislice;
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
uint32_t slice_enable_mask = BIT3;
/* 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 bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX); /* 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 uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1; /* 0x0=External data pin(slice0/A RX mode), 0x1=Concatenate data */
/* Only for slice0/A and RX mode set input_slice to 1 */
const bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX);
/* 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_CONCAT_ORDER(concat_order)
| SGPIO_MUX_CFG_CONCAT_ENABLE(concat_enable)
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) /* Select qualifier slice A(0x0) */
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) /* Select qualifier pin SGPIO9(0x1) */
| 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_PIN_MODE(0) /* Source Clock Pin 0x0 = SGPIO8 */
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) /* External clock signal(pin) selected */
SGPIO_MUX_CFG_CONCAT_ORDER(concat_order)
| SGPIO_MUX_CFG_CONCAT_ENABLE(concat_enable)
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) // Select qualifier slice A
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) // Select qualifier pin SGPIO9
| SGPIO_MUX_CFG_QUALIFIER_MODE(3) // External SGPIO
| SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) // Select clock source slice D
| SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) // Source clock pin = SGPIO8
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) // External clock signal selected
;
SGPIO_SLICE_MUX_CFG(slice_index) =
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) /* 0x0=Use normal qualifier. */
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(3) /* 0x3=Shift 1 byte(8bits) per clock. */
| SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) /* 0x0=Detect rising edge. (Condition for input bit match interrupt) */
| SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) /* 0x0=Normal clock. */
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) /* 0x1=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_MATCH_MODE(0) /* 0x0=Do not match data */
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) // Use normal qualifier
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(3) // Shift 1 byte (8 bits) per clock
| SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) // Detect rising edge
| SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) // Normal clock
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) // Use external clock from a pin or other slice
| SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(0) // Use rising clock edge
| 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_COUNT(slice_index) = 0; // External clock, don't care
SGPIO_POS(slice_index) = SGPIO_POS_POS_RESET(pos) | SGPIO_POS_POS(pos);
SGPIO_REG(slice_index) = 0x00000000; // Primary output data register
SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register
// clang-format on
SGPIO_PRESET(slice_index) = 0; // External clock, don't care
SGPIO_COUNT(slice_index) = 0; // External clock, don't care
SGPIO_POS(slice_index) =
SGPIO_POS_POS_RESET(pos)
| SGPIO_POS_POS(pos)
;
SGPIO_REG(slice_index) = 0x00000000; // Primary output data register
SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register
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_CONCAT_ORDER(0) /* Self-loop */
| SGPIO_MUX_CFG_CONCAT_ENABLE(1)
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) /* Select qualifier slice A(0x0) */
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) /* Select qualifier pin SGPIO9(0x1) */
| 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_PIN_MODE(0) /* Source Clock Pin 0x0 = SGPIO8 */
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) /* External clock signal(pin) selected */
SGPIO_MUX_CFG_CONCAT_ORDER(0) // Self-loop
| SGPIO_MUX_CFG_CONCAT_ENABLE(1) // Concatenate data
| SGPIO_MUX_CFG_QUALIFIER_SLICE_MODE(0) // Select qualifier slice A
| SGPIO_MUX_CFG_QUALIFIER_PIN_MODE(1) // Select qualifier pin SGPIO9
| SGPIO_MUX_CFG_QUALIFIER_MODE(3) // External SGPIO
| SGPIO_MUX_CFG_CLK_SOURCE_SLICE_MODE(0) // Select clock source slice D
| SGPIO_MUX_CFG_CLK_SOURCE_PIN_MODE(0) // Source clock pin = SGPIO8
| SGPIO_MUX_CFG_EXT_CLK_ENABLE(1) // External clock signal selected
;
SGPIO_SLICE_MUX_CFG(slice_gpdma) =
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) /* 0x0=Use normal qualifier. */
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(0) /* 0x0=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_INV_OUT_CLK(0) /* 0x0=Normal clock. */
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) /* 0x1=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_MATCH_MODE(0) /* 0x0=Do not match data */
SGPIO_SLICE_MUX_CFG_INV_QUALIFIER(0) // Use normal qualifier
| SGPIO_SLICE_MUX_CFG_PARALLEL_MODE(0) // Shift 1 bit per clock
| SGPIO_SLICE_MUX_CFG_DATA_CAPTURE_MODE(0) // Detect rising edge
| SGPIO_SLICE_MUX_CFG_INV_OUT_CLK(0) // Normal clock
| SGPIO_SLICE_MUX_CFG_CLKGEN_MODE(1) // Use external clock from a pin or other slice
| SGPIO_SLICE_MUX_CFG_CLK_CAPTURE_MODE(0) // Use rising clock edge
| 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_COUNT(slice_gpdma) = 0; // External clock, don't care
SGPIO_POS(slice_gpdma) = SGPIO_POS_POS_RESET(0x1f) | SGPIO_POS_POS(0x1f);
SGPIO_REG(slice_gpdma) =
0x11111111; // Primary output data register, LSB -> out
SGPIO_REG_SS(slice_gpdma) =
0x11111111; // Shadow output data register, LSB -> out1
SGPIO_PRESET(slice_gpdma) = 0; // External clock, don't care
SGPIO_COUNT(slice_gpdma) = 0; // External clock, don't care
SGPIO_POS(slice_gpdma) =
SGPIO_POS_POS_RESET(0x1f)
| SGPIO_POS_POS(0x1f)
;
SGPIO_REG(slice_gpdma) = 0x11111111; // Primary output data register, LSB -> out
SGPIO_REG_SS(slice_gpdma) = 0x11111111; // Shadow output data register, LSB -> out1
slice_enable_mask |= (1 << slice_gpdma);
}
@ -242,24 +263,26 @@ void sgpio_configure(
SGPIO_CTRL_ENABLE = slice_enable_mask;
}
void sgpio_cpld_stream_enable(sgpio_config_t* const config) {
(void)config;
void sgpio_cpld_stream_enable(sgpio_config_t* const config)
{
(void) config;
// Enable codec data stream.
SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */
}
void sgpio_cpld_stream_disable(sgpio_config_t* const config) {
(void)config;
void sgpio_cpld_stream_disable(sgpio_config_t* const config)
{
(void) config;
// Disable codec data stream.
SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */
}
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config) {
(void)config;
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config)
{
(void) config;
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
}
#ifdef RAD1O
/* The rad1o hardware has a bug which makes it
* necessary to also switch between the two options based
@ -274,24 +297,28 @@ static bool sgpio_invert = false;
/* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert
* 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) */
bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0;
/* 0.13: P1_18 */
if( !sgpio_invert & !tx_mode) {
if (!sgpio_invert & !tx_mode) {
gpio_write(config->gpio_rx_q_invert, 1);
} else if( !sgpio_invert & tx_mode) {
} else if (!sgpio_invert & tx_mode) {
gpio_write(config->gpio_rx_q_invert, 0);
} else if( sgpio_invert & !tx_mode) {
} else if (sgpio_invert & !tx_mode) {
gpio_write(config->gpio_rx_q_invert, 0);
} else if( sgpio_invert & tx_mode) {
} else if (sgpio_invert & tx_mode) {
gpio_write(config->gpio_rx_q_invert, 1);
}
}
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) {
if( invert ) {
void sgpio_cpld_stream_rx_set_q_invert(
sgpio_config_t* const config,
const uint_fast8_t invert)
{
if (invert) {
sgpio_invert = true;
} else {
sgpio_invert = false;
@ -301,7 +328,10 @@ void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_
}
#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);
}
#endif

View File

@ -42,18 +42,14 @@ typedef struct sgpio_config_t {
void sgpio_configure_pin_functions(sgpio_config_t* const config);
void sgpio_test_interface(sgpio_config_t* const config);
void sgpio_set_slice_mode(
sgpio_config_t* const config,
const bool multi_slice
);
void sgpio_configure(
sgpio_config_t* const config,
const sgpio_direction_t direction
);
void sgpio_set_slice_mode(sgpio_config_t* const config, 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_disable(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

@ -29,15 +29,15 @@ uint8_t clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
/* write to single register */
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
{
const uint8_t data_tx[] = { reg, val };
const uint8_t data_tx[] = {reg, val};
si5351c_write(drv, data_tx, 2);
}
/* read single register */
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg)
{
const uint8_t data_tx[] = { reg };
uint8_t data_rx[] = { 0x00 };
const uint8_t data_tx[] = {reg};
uint8_t data_rx[] = {0x00};
i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1);
return data_rx[0];
}
@ -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
* 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);
}
@ -54,30 +57,30 @@ void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const
/* Disable all CLKx outputs. */
void si5351c_disable_all_outputs(si5351c_driver_t* const drv)
{
uint8_t data[] = { 3, 0xFF };
uint8_t data[] = {3, 0xFF};
si5351c_write(drv, data, sizeof(data));
}
/* Turn off OEB pin control for all CLKx */
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv)
{
uint8_t data[] = { 9, 0xFF };
uint8_t data[] = {9, 0xFF};
si5351c_write(drv, data, sizeof(data));
}
/* Power down all CLKx */
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
{
uint8_t data[] = { 16
, 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_INT_MODE
};
uint8_t data[] = {
16,
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_INT_MODE};
si5351c_write(drv, data, sizeof(data));
}
@ -88,7 +91,7 @@ void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
*/
void si5351c_set_crystal_configuration(si5351c_driver_t* const drv)
{
uint8_t data[] = { 183, 0x80 };
uint8_t data[] = {183, 0x80};
si5351c_write(drv, data, sizeof(data));
}
@ -98,7 +101,7 @@ void si5351c_set_crystal_configuration(si5351c_driver_t* const drv)
*/
void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv)
{
uint8_t data[] = { 187, 0xD0 };
uint8_t data[] = {187, 0xD0};
si5351c_write(drv, data, sizeof(data));
}
@ -110,7 +113,7 @@ void si5351c_enable_xo_and_ms_fanout(si5351c_driver_t* const drv)
*/
void si5351c_configure_pll_sources(si5351c_driver_t* const drv)
{
uint8_t data[] = { 15, 0x08 };
uint8_t data[] = {15, 0x08};
si5351c_write(drv, data, sizeof(data));
}
@ -119,7 +122,7 @@ void si5351c_configure_pll_sources(si5351c_driver_t* const drv)
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv)
{
/*PLLA: 25MHz XTAL * (0x0e00+512)/128 = 800mhz -> int mode */
uint8_t data[] = { 26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 };
uint8_t data[] = {26, 0x00, 0x01, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00};
si5351c_write(drv, data, sizeof(data));
/*PLLB: 10MHz CLKIN * (0x2600+512)/128 = 800mhz */
@ -131,14 +134,17 @@ void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv)
void si5351c_reset_pll(si5351c_driver_t* const drv)
{
/* reset PLLA and PLLB */
uint8_t data[] = { 177, 0xA0 };
uint8_t data[] = {177, 0xA0};
si5351c_write(drv, data, sizeof(data));
}
void si5351c_configure_multisynth(si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3,
const uint_fast8_t r_div)
void si5351c_configure_multisynth(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint32_t p1,
const uint32_t p2,
const uint32_t p3,
const uint_fast8_t r_div)
{
/*
* TODO: Check for p3 > 0? 0 has no meaning in fractional mode?
@ -154,19 +160,21 @@ void si5351c_configure_multisynth(si5351c_driver_t* const drv,
*/
const uint_fast8_t register_number = 42 + (ms_number * 8);
uint8_t data[] = {
register_number,
(p3 >> 8) & 0xFF,
(p3 >> 0) & 0xFF,
(r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3),
(p1 >> 8) & 0xFF,
(p1 >> 0) & 0xFF,
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
(p2 >> 8) & 0xFF,
(p2 >> 0) & 0xFF };
register_number,
(p3 >> 8) & 0xFF,
(p3 >> 0) & 0xFF,
(r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3),
(p1 >> 8) & 0xFF,
(p1 >> 0) & 0xFF,
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
(p2 >> 8) & 0xFF,
(p2 >> 0) & 0xFF};
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;
#ifdef RAD1O
@ -186,23 +194,37 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll
#endif
/* Clock to CPU is deactivated as it is not used and creates noise */
/* External clock output is kept in current state */
uint8_t data[] = {16
,SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA)
,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_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*/
};
uint8_t data[] = {
16,
SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA),
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_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));
}
#define SI5351C_CLK_ENABLE(x) (0<<x)
#define SI5351C_CLK_DISABLE(x) (1<<x)
#define SI5351C_REG_OUTPUT_EN (3)
#define SI5351C_REG_CLK3_CTRL (19)
#define SI5351C_CLK_ENABLE(x) (0 << x)
#define SI5351C_CLK_DISABLE(x) (1 << x)
#define SI5351C_REG_OUTPUT_EN (3)
#define SI5351C_REG_CLK3_CTRL (19)
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
{
@ -210,44 +232,46 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
/* 7: Clock to CPU is deactivated as it is not used and creates noise */
/* 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[] = { SI5351C_REG_OUTPUT_EN,
SI5351C_CLK_ENABLE(0) |
SI5351C_CLK_ENABLE(1) |
SI5351C_CLK_ENABLE(2) |
SI5351C_CLK_DISABLE(3) |
SI5351C_CLK_ENABLE(4) |
SI5351C_CLK_ENABLE(5) |
SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_DISABLE(7)
};
uint8_t data[] = {
SI5351C_REG_OUTPUT_EN,
SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(2) |
SI5351C_CLK_DISABLE(3) | SI5351C_CLK_ENABLE(4) |
SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_DISABLE(7)};
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){
uint8_t data[] = {16, 0};
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};
if(ms_number < 8){
data[0] = 16 + ms_number;
data[1] = si5351c_read_single(drv, data[0]);
if (ms_number < 8) {
data[0] = 16 + ms_number;
data[1] = si5351c_read_single(drv, data[0]);
if(on)
data[1] |= SI5351C_CLK_INT_MODE;
else
data[1] &= ~(SI5351C_CLK_INT_MODE);
if (on) {
data[1] |= SI5351C_CLK_INT_MODE;
} else {
data[1] &= ~(SI5351C_CLK_INT_MODE);
}
si5351c_write(drv, data, 2);
}
si5351c_write(drv, data, 2);
}
}
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source)
{
if( source != active_clock_source ) {
if (source != active_clock_source) {
si5351c_configure_clock_control(drv, source);
active_clock_source = 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;
}
@ -256,36 +280,40 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
/* Set optput in output enable register */
uint8_t output_enable = si5351c_read_single(drv, 3);
output_enable = output_enable & !SI5351C_CLK_DISABLE(3);
if(enable)
if (enable) {
output_enable = output_enable | SI5351C_CLK_ENABLE(3);
else
} else {
output_enable = output_enable | SI5351C_CLK_DISABLE(3);
}
uint8_t oe_data[] = {SI5351C_REG_OUTPUT_EN, output_enable};
si5351c_write(drv, oe_data, 2);
/* Configure clock to 10MHz (TODO customisable?) */
si5351c_configure_multisynth(drv, 3, 80*128-512, 0, 1, 0);
si5351c_configure_multisynth(drv, 3, 80 * 128 - 512, 0, 1, 0);
/* Set power up/doen in CLK3 control register*/
uint8_t pll;
#ifdef RAD1O
#ifdef RAD1O
/* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A;
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
if (active_clock_source == PLL_SOURCE_CLKIN) {
/* PLLB on CLKIN */
pll = SI5351C_CLK_PLL_SRC_B;
} else {
/* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A;
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE)
if (active_clock_source == PLL_SOURCE_CLKIN) {
/* PLLB on CLKIN */
pll = SI5351C_CLK_PLL_SRC_B;
} else {
/* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A;
}
#endif
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);
else
}
#endif
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);
} else {
clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
}
uint8_t clk3_data[] = {SI5351C_REG_CLK3_CTRL, clk3_ctrl};
si5351c_write(drv, clk3_data, 2);
}

View File

@ -24,8 +24,7 @@
#define __SI5351C_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
#include <stdint.h>
@ -33,31 +32,31 @@ extern "C"
#include "i2c_bus.h"
#define SI_INTDIV(x) (x*128-512)
#define SI_INTDIV(x) (x * 128 - 512)
#define SI5351C_CLK_POWERDOWN (1<<7)
#define SI5351C_CLK_INT_MODE (1<<6)
#define SI5351C_CLK_FRAC_MODE (0<<6)
#define SI5351C_CLK_POWERDOWN (1 << 7)
#define SI5351C_CLK_INT_MODE (1 << 6)
#define SI5351C_CLK_FRAC_MODE (0 << 6)
#define SI5351C_CLK_PLL_SRC(x) (x<<5)
#define SI5351C_CLK_PLL_SRC_A 0
#define SI5351C_CLK_PLL_SRC_B 1
#define SI5351C_CLK_PLL_SRC(x) (x << 5)
#define SI5351C_CLK_PLL_SRC_A 0
#define SI5351C_CLK_PLL_SRC_B 1
#define SI5351C_CLK_INV (1<<4)
#define SI5351C_CLK_INV (1 << 4)
#define SI5351C_CLK_SRC(x) (x<<2)
#define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
#define SI5351C_CLK_SRC(x) (x << 2)
#define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
#define SI5351C_CLK_IDRV(x) (x<<0)
#define SI5351C_CLK_IDRV(x) (x << 0)
#define SI5351C_CLK_IDRV_2MA 0
#define SI5351C_CLK_IDRV_4MA 1
#define SI5351C_CLK_IDRV_6MA 2
#define SI5351C_CLK_IDRV_8MA 3
#define SI5351C_LOS (1<<4)
#define SI5351C_LOS (1 << 4)
enum pll_sources {
PLL_SOURCE_UNINITIALIZED = -1,
@ -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_multisynth(si5351c_driver_t* const drv);
void si5351c_reset_pll(si5351c_driver_t* const drv);
void si5351c_configure_multisynth(si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint32_t p1, const uint32_t p2, const uint32_t p3,
const uint_fast8_t r_div);
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source);
void si5351c_configure_multisynth(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint32_t p1,
const uint32_t p2,
const uint32_t p3,
const uint_fast8_t r_div);
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_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);
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);
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);
#ifdef __cplusplus

View File

@ -21,18 +21,25 @@
#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);
}
void spi_bus_stop(spi_bus_t* const bus) {
void spi_bus_stop(spi_bus_t* const 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);
}
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);
}

View File

@ -38,12 +38,18 @@ struct spi_bus_t {
void (*start)(spi_bus_t* const bus, const void* const config);
void (*stop)(spi_bus_t* const bus);
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_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_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,10 +24,11 @@
#include <libopencm3/lpc43xx/rgu.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;
if( bus->obj == (void*)SSP0_BASE ) {
if (bus->obj == (void*) SSP0_BASE) {
/* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST;
}
@ -37,39 +38,36 @@ void spi_ssp_start(spi_bus_t* const bus, const void* const _config) {
SSP_CR1(bus->obj) = 0;
SSP_CPSR(bus->obj) = config->clock_prescale_rate;
SSP_CR0(bus->obj) =
(config->serial_clock_rate << 8)
| SSP_CPOL_0_CPHA_0
| SSP_FRAME_SPI
| config->data_bits
;
SSP_CR0(bus->obj) = (config->serial_clock_rate << 8) | SSP_CPOL_0_CPHA_0 |
SSP_FRAME_SPI | config->data_bits;
SSP_CR1(bus->obj) =
SSP_SLAVE_OUT_ENABLE
| SSP_MASTER
| SSP_ENABLE
| SSP_MODE_NORMAL
;
SSP_SLAVE_OUT_ENABLE | SSP_MASTER | SSP_ENABLE | SSP_MODE_NORMAL;
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;
}
static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus) {
while( (SSP_SR(bus->obj) & SSP_SR_TNF) == 0 );
static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus)
{
while ((SSP_SR(bus->obj) & SSP_SR_TNF) == 0) {}
}
static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus) {
while( (SSP_SR(bus->obj) & SSP_SR_RNE) == 0 );
static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus)
{
while ((SSP_SR(bus->obj) & SSP_SR_RNE) == 0) {}
}
static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus) {
while( SSP_SR(bus->obj) & SSP_SR_BSY );
static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus)
{
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);
SSP_DR(bus->obj) = data;
spi_ssp_wait_for_not_busy(bus);
@ -77,23 +75,27 @@ static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data)
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 bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS;
gpio_clear(config->gpio_select);
for(size_t i=0; i<count; i++) {
for (size_t i = 0; i < count; i++) {
const size_t data_count = transfers[i].count;
if( word_size_u16 ) {
if (word_size_u16) {
uint16_t* const data = transfers[i].data;
for(size_t j=0; j<data_count; j++) {
for (size_t j = 0; j < data_count; j++) {
data[j] = spi_ssp_transfer_word(bus, data[j]);
}
} else {
uint8_t* const data = transfers[i].data;
for(size_t j=0; j<data_count; j++) {
for (size_t j = 0; j < data_count; j++) {
data[j] = spi_ssp_transfer_word(bus, data[j]);
}
}
@ -101,9 +103,10 @@ void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const t
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[] = {
{ data, count },
{data, count},
};
spi_ssp_transfer_gather(bus, transfers, 1);
}

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_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_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/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_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);
}

View File

@ -28,4 +28,4 @@
void baseband_streaming_enable(sgpio_config_t* const sgpio_config);
void baseband_streaming_disable(sgpio_config_t* const sgpio_config);
#endif/*__STREAMING_H__*/
#endif /*__STREAMING_H__*/

View File

@ -30,7 +30,7 @@
#include <sgpio.h>
#include <operacake.h>
#define FREQ_ONE_MHZ (1000*1000)
#define FREQ_ONE_MHZ (1000 * 1000)
#define MIN_LP_FREQ_MHZ (0)
#define MAX_LP_FREQ_MHZ (2150)
@ -38,17 +38,18 @@
#define MIN_BYPASS_FREQ_MHZ (2150)
#define MAX_BYPASS_FREQ_MHZ (2750)
#define MIN_HP_FREQ_MHZ (2750)
#define MIN_HP_FREQ_MHZ (2750)
#define MID1_HP_FREQ_MHZ (3600)
#define MID2_HP_FREQ_MHZ (5100)
#define MAX_HP_FREQ_MHZ (7250)
#define MAX_HP_FREQ_MHZ (7250)
#define MIN_LO_FREQ_HZ (84375000)
#define MAX_LO_FREQ_HZ (5400000000ULL)
static uint32_t max2837_freq_nominal_hz=2560000000;
static uint32_t max2837_freq_nominal_hz = 2560000000;
uint64_t freq_cache = 100000000;
/*
* Set freq/tuning between 0MHz to 7250 MHz (less than 16bits really used)
* 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);
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);
#ifdef RAD1O
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);
max2837_set_frequency(&max2837, real_mixer_freq_hz - freq);
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);
MAX2837_freq_hz = (freq_mhz * FREQ_ONE_MHZ) + freq_hz;
/* mixer_freq_mhz <= not used in Bypass mode */
max2837_set_frequency(&max2837, MAX2837_freq_hz);
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 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) {
/* IF is graduated from 2350 MHz to 2650 MHz */
max2837_freq_nominal_hz = 2350000000 + ((freq - 3600000000) / 5);
@ -107,13 +106,12 @@ bool set_freq(const uint64_t freq)
real_mixer_freq_hz = mixer_set_frequency(&mixer, mixer_freq_mhz);
max2837_set_frequency(&max2837, freq - real_mixer_freq_hz);
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}else
{
} else {
/* Error freq_mhz too high */
success = false;
}
max2837_set_mode(&max2837, prior_max2837_mode);
if( success ) {
if (success) {
freq_cache = freq;
hackrf_ui()->set_frequency(freq);
#ifdef HACKRF_ONE
@ -123,16 +121,18 @@ bool set_freq(const uint64_t freq)
return success;
}
bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
const rf_path_filter_t path)
bool set_freq_explicit(
const uint64_t if_freq_hz,
const uint64_t lo_freq_hz,
const rf_path_filter_t path)
{
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 ((if_freq_hz < ((uint64_t) MIN_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ)) ||
(if_freq_hz > ((uint64_t) MAX_BYPASS_FREQ_MHZ * FREQ_ONE_MHZ))) {
return false;
}
if ((path != RF_PATH_FILTER_BYPASS) &&
((lo_freq_hz < MIN_LO_FREQ_HZ) || (lo_freq_hz > MAX_LO_FREQ_HZ))) {
((lo_freq_hz < MIN_LO_FREQ_HZ) || (lo_freq_hz > MAX_LO_FREQ_HZ))) {
return false;
}
@ -148,7 +148,7 @@ bool set_freq_explicit(const uint64_t if_freq_hz, const uint64_t lo_freq_hz,
sgpio_cpld_stream_rx_set_q_invert(&sgpio_config, 0);
}
if (path != RF_PATH_FILTER_BYPASS) {
(void)mixer_set_frequency(&mixer, lo_freq_hz / FREQ_ONE_MHZ);
(void) mixer_set_frequency(&mixer, lo_freq_hz / FREQ_ONE_MHZ);
}
return true;
}

View File

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

View File

@ -26,281 +26,357 @@
/* Pixel data within a font or bitmap byte is "reversed": LSB is left-most pixel. */
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, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x48, 0x48, 0x48, 0xff, 0x24, 0x24, 0xff, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x78, 0x14, 0x14, 0x14, 0x18, 0x30, 0x50, 0x50, 0x50, 0x3c, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x46, 0x29, 0x29, 0x19, 0x16, 0x68, 0x98, 0x94, 0x94, 0x62, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x14, 0x88, 0x54, 0x72, 0x22, 0x62, 0x9c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 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, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x00,
0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 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, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x5a, 0x5a, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x10, 0x0c, 0x10, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x30, 0x28, 0x28, 0x24, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0x04, 0x04, 0x04, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x22, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x18, 0x04, 0x18, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x30, 0x40, 0x30, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x30, 0x08, 0x08, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x59, 0x55, 0x55, 0x55, 0x39, 0x01, 0x02, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x14, 0x14, 0x14, 0x14, 0x22, 0x3e, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x22, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x72, 0x42, 0x42, 0x44, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x82, 0x42, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x42, 0x66, 0x66, 0x5a, 0x5a, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x42, 0x46, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x10, 0x60, 0x00,
0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x12, 0x22, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3c, 0x42, 0x02, 0x02, 0x0c, 0x30, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x41, 0x41, 0x49, 0x49, 0x55, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22, 0x41, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00,
0x00, 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00,
0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x7c, 0x42, 0x62, 0x5c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x1a, 0x26, 0x42, 0x42, 0x42, 0x26, 0x1a, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x04, 0x02, 0x02, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x7e, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x7e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x22, 0x22, 0x22, 0x1c, 0x02, 0x3e, 0x42, 0x42, 0x3c,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e,
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 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
};
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, 0x24, 0x24, 0x24, 0x24,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48,
0x48, 0x48, 0xff, 0x24, 0x24, 0xff, 0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x78, 0x14, 0x14, 0x14, 0x18, 0x30, 0x50, 0x50, 0x50, 0x3c, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x29, 0x29, 0x19, 0x16, 0x68, 0x98, 0x94,
0x94, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x24, 0x14, 0x88,
0x54, 0x72, 0x22, 0x62, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 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, 0x02, 0x04, 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x08,
0x08, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
0x10, 0x10, 0xfe, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 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, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x10, 0x10,
0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x24, 0x42, 0x42, 0x5a, 0x5a, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x0a, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x20, 0x20, 0x10, 0x08, 0x04,
0x02, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x20, 0x20, 0x10, 0x0c,
0x10, 0x20, 0x20, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30,
0x28, 0x28, 0x24, 0x24, 0x22, 0x7e, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7c, 0x04, 0x04, 0x04, 0x3c, 0x40, 0x40, 0x40, 0x40, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x04, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x44,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x20, 0x10, 0x10,
0x10, 0x08, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x42,
0x24, 0x18, 0x24, 0x42, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1c, 0x22, 0x42, 0x42, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00,
0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20,
0x18, 0x04, 0x18, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x30, 0x40, 0x30, 0x08, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x40, 0x40, 0x30, 0x08, 0x08, 0x00,
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x41, 0x59, 0x55,
0x55, 0x55, 0x39, 0x01, 0x02, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x14,
0x14, 0x14, 0x14, 0x22, 0x3e, 0x22, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x44,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x22, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x02, 0x02,
0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x02, 0x02, 0x02, 0x7e, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x72, 0x42, 0x42, 0x44, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42,
0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x82, 0x42, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0x82, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x66, 0x66, 0x5a, 0x5a,
0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x46,
0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x24, 0x18, 0x10, 0x60, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x42, 0x42,
0x42, 0x3e, 0x12, 0x22, 0x22, 0x42, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3c, 0x42, 0x02, 0x02, 0x0c, 0x30, 0x40, 0x40, 0x42, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x41, 0x22, 0x22,
0x22, 0x14, 0x14, 0x14, 0x14, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
0x41, 0x41, 0x49, 0x49, 0x55, 0x55, 0x55, 0x22, 0x22, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x22, 0x41, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x40, 0x20, 0x10, 0x10,
0x08, 0x08, 0x04, 0x02, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, 0x00, 0x00,
0x00, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x10, 0x28, 0x44, 0x44, 0x82, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x40, 0x7c, 0x42, 0x62, 0x5c,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x1a, 0x26, 0x42, 0x42,
0x42, 0x26, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
0x04, 0x02, 0x02, 0x02, 0x04, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
0x40, 0x40, 0x58, 0x64, 0x42, 0x42, 0x42, 0x64, 0x58, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x24, 0x42, 0x7e, 0x02, 0x04, 0x78, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x08, 0x7e, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x22,
0x22, 0x22, 0x1c, 0x02, 0x3e, 0x42, 0x42, 0x3c, 0x00, 0x00, 0x00, 0x02, 0x02,
0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x22, 0x12, 0x0a,
0x0e, 0x12, 0x22, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x08, 0x08,
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 = {
{ 8, 16 },
font_fixed_8x16_glyph_data,
0x20, 95,
(8 * 16 + 7U) >> 3
};
static const ui_font_t font_fixed_8x16 =
{{8, 16}, font_fixed_8x16_glyph_data, 0x20, 95, (8 * 16 + 7U) >> 3};
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,
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,
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,
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, 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, 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 = {
{ 24, 19 },
font_fixed_24x19_glyph_data,
0x30, 10,
(24 * 19 + 7U) >> 3
};
static const ui_font_t font_fixed_24x19 =
{{24, 19}, font_fixed_24x19_glyph_data, 0x30, 10, (24 * 19 + 7U) >> 3};
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,
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,
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, 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,
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,
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,
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, 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, 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, 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, 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, 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 = {
{ 16, 14 },
font_fixed_16x14_glyph_data,
0x30, 10,
(16 * 14 + 7U) >> 3
};
static const ui_font_t font_fixed_16x14 =
{{16, 14}, font_fixed_16x14_glyph_data, 0x30, 10, (16 * 14 + 7U) >> 3};
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 = {
{ 24, 24 }, bitmap_amp_rx_data
};
static const ui_bitmap_t bitmap_amp_rx = {{24, 24}, bitmap_amp_rx_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 = {
{ 24, 24 }, bitmap_amp_tx_data
};
static const ui_bitmap_t bitmap_amp_tx = {{24, 24}, bitmap_amp_tx_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 = {
{ 24, 24 }, bitmap_antenna_data
};
static const ui_bitmap_t bitmap_antenna = {{24, 24}, bitmap_antenna_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 = {
{ 24, 24 }, bitmap_filter_hp_data
};
static const ui_bitmap_t bitmap_filter_hp = {{24, 24}, bitmap_filter_hp_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 = {
{ 24, 24 }, bitmap_filter_lp_data
};
static const ui_bitmap_t bitmap_filter_lp = {{24, 24}, bitmap_filter_lp_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 = {
{ 24, 24 }, bitmap_mixer_data
};
static const ui_bitmap_t bitmap_mixer = {{24, 24}, bitmap_mixer_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 = {
{ 24, 24 }, bitmap_oscillator_data
};
static const ui_bitmap_t bitmap_oscillator = {{24, 24}, bitmap_oscillator_data};
static const uint8_t bitmap_wire_8_data[] = {
0xff, 0xff
};
static const uint8_t bitmap_wire_8_data[] = {0xff, 0xff};
static const ui_bitmap_t bitmap_wire_8 = {
{ 2, 8 }, bitmap_wire_8_data
};
static const ui_bitmap_t bitmap_wire_8 = {{2, 8}, bitmap_wire_8_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 = {
{ 24, 24 }, bitmap_wire_24_data
};
static const ui_bitmap_t bitmap_wire_24 = {{24, 24}, bitmap_wire_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 = {
{ 24, 24 }, bitmap_blank_24_data
};
static const ui_bitmap_t bitmap_blank_24 = {{24, 24}, bitmap_blank_24_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 = {
{ 16, 24 }, bitmap_waves_rx_data
};
static const ui_bitmap_t bitmap_waves_rx = {{16, 24}, bitmap_waves_rx_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 = {
{ 16, 24 }, bitmap_waves_tx_data
};
static const ui_bitmap_t bitmap_waves_tx = {{16, 24}, bitmap_waves_tx_data};
__attribute__((unused)) static ui_color_t portapack_color_rgb(
const uint_fast8_t r,
const uint_fast8_t g,
const uint_fast8_t b
) {
const uint_fast8_t b)
{
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;
}
static const ui_color_t color_background = { 0x001f };
static const ui_color_t color_foreground = { 0xffff };
static const ui_color_t color_background = {0x001f};
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 = {
.x = point.x + font_fixed_8x16.glyph_size.width * field_width,
.y = point.y
};
.y = point.y};
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++) {
const char c = ((i == 0) || (value != 0)) ? ('0' + value % 10) : ' ';
value /= 10;
const ui_bitmap_t glyph = portapack_font_glyph(&font_fixed_8x16, c);
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;
}
static ui_point_t portapack_lcd_draw_string(ui_point_t point, const char* s) {
while(*s) {
static ui_point_t portapack_lcd_draw_string(ui_point_t point, const char* s)
{
while (*s) {
const char c = *(s++);
const ui_bitmap_t glyph = portapack_font_glyph(&font_fixed_8x16, c);
portapack_draw_bitmap(point, glyph, color_foreground, color_background);
@ -316,24 +392,24 @@ typedef struct draw_list_t {
} draw_list_t;
static draw_list_t radio_draw_list[] = {
{ &bitmap_antenna, { 32, 64 } },
{ &bitmap_wire_8, { 43, 88 } },
{ &bitmap_wire_24, { 32, 96 } },
{ &bitmap_wire_8, { 43, 120 } },
{ &bitmap_filter_hp, { 32, 128 } },
{ &bitmap_wire_8, { 43, 152 } },
{ &bitmap_mixer, { 32, 160 } },
{ &bitmap_wire_8, { 43, 184 } },
{ &bitmap_amp_rx, { 32, 192 } },
{ &bitmap_wire_8, { 43, 216 } },
{ &bitmap_mixer, { 32, 224 } },
{ &bitmap_wire_8, { 43, 248 } },
{ &bitmap_filter_lp, { 32, 256 } },
{ &bitmap_wire_8, { 43, 280 } },
{ &bitmap_amp_rx, { 32, 288 } },
{ &bitmap_wire_8, { 43, 312 } },
{ &bitmap_oscillator, { 208, 288 } },
{ &bitmap_blank_24, { 60, 60 } },
{&bitmap_antenna, {32, 64}},
{&bitmap_wire_8, {43, 88}},
{&bitmap_wire_24, {32, 96}},
{&bitmap_wire_8, {43, 120}},
{&bitmap_filter_hp, {32, 128}},
{&bitmap_wire_8, {43, 152}},
{&bitmap_mixer, {32, 160}},
{&bitmap_wire_8, {43, 184}},
{&bitmap_amp_rx, {32, 192}},
{&bitmap_wire_8, {43, 216}},
{&bitmap_mixer, {32, 224}},
{&bitmap_wire_8, {43, 248}},
{&bitmap_filter_lp, {32, 256}},
{&bitmap_wire_8, {43, 280}},
{&bitmap_amp_rx, {32, 288}},
{&bitmap_wire_8, {43, 312}},
{&bitmap_oscillator, {208, 288}},
{&bitmap_blank_24, {60, 60}},
};
typedef enum {
@ -349,23 +425,33 @@ typedef enum {
RADIO_DRAW_LIST_ITEM_WAVES = 17,
} 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;
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;
}
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);
}
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);
point = portapack_lcd_draw_int(point, db, 2);
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 round_offset = lsd / 2;
@ -380,12 +466,20 @@ static ui_point_t portapack_ui_draw_bw_mhz(const radio_draw_list_item_t item, co
return portapack_lcd_draw_string(point, " MHz");
}
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);
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);
}
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 ) {
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) {
radio_draw_list[item].bitmap = bitmap;
portapack_draw_radio_path_item(item);
}
@ -394,117 +488,154 @@ 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 bool portapack_lna_on = false;
static void portapack_radio_path_redraw() {
for( size_t i=0; i<ARRAY_SIZEOF(radio_draw_list); i++ ) {
static void portapack_radio_path_redraw()
{
for (size_t i = 0; i < ARRAY_SIZEOF(radio_draw_list); 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_backlight(true);
portapack_radio_path_redraw();
}
static void portapack_ui_deinit(void) {
static void portapack_ui_deinit(void)
{
portapack_clear_display(color_background);
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] = " ";
ui_point_t point = { 240 - 20, 16 };
ui_point_t point = {240 - 20, 16};
uint64_t value = frequency;
char s[10];
for(int i=0; i<10; i++) {
for (int i = 0; i < 10; i++) {
const char c = '0' + value % 10;
s[i] = ((i>=6) && (value == 0)) ? ' ' : c;
s[i] = ((i >= 6) && (value == 0)) ? ' ' : c;
value /= 10;
}
for(int i=0; i<10; i++) {
for (int i = 0; i < 10; 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;
if( (i==3) || (i==6) || (i==9) ) {
if ((i == 3) || (i == 6) || (i == 9)) {
point.x -= 4;
}
if( c != last[i] ) {
if (c != last[i]) {
const ui_bitmap_t glyph = portapack_font_glyph(font, c);
if( c == ' ' ) {
if (c == ' ') {
/* Blank out leading zeros. */
const ui_rect_t rect = { point, glyph.size };
const ui_rect_t rect = {point, glyph.size};
portapack_fill_rectangle(rect, color_background);
} else {
portapack_draw_bitmap(point, glyph, color_foreground, color_background);
portapack_draw_bitmap(
point,
glyph,
color_foreground,
color_background);
}
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
ui_point_t point = { VALUES_X, 320 - 1 * 16 };
portapack_lcd_draw_int(point, sample_rate, 8);
#else
(void)sample_rate;
(void) sample_rate;
#endif
}
static void portapack_ui_set_direction(const rf_path_direction_t direction) {
switch(direction) {
static void portapack_ui_set_direction(const rf_path_direction_t direction)
{
switch (direction) {
case RF_PATH_DIRECTION_TX:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_waves_tx);
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_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_WAVES,
&bitmap_waves_tx);
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, " ");
break;
case RF_PATH_DIRECTION_RX:
portapack_radio_path_item_update(RADIO_DRAW_LIST_ITEM_WAVES, &bitmap_waves_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);
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_WAVES,
&bitmap_waves_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;
case RF_PATH_DIRECTION_OFF:
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;
}
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);
}
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_radio_path_item_update(RADIO_DRAW_LIST_ITEM_RF_AMP, lna_on
? ((portapack_direction == RF_PATH_DIRECTION_TX) ? &bitmap_amp_tx : &bitmap_amp_rx)
: &bitmap_wire_24);
portapack_radio_path_item_update(
RADIO_DRAW_LIST_ITEM_RF_AMP,
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" : " ";
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);
}
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);
}
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?
* 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.
@ -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);
}
static void portapack_ui_set_first_if_frequency(const uint64_t frequency) {
(void)frequency;
static void portapack_ui_set_first_if_frequency(const uint64_t frequency)
{
(void) frequency;
}
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);
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);
switch(filter) {
switch (filter) {
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;
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;
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;
}
}
static void portapack_ui_set_antenna_bias(bool antenna_bias) {
(void)antenna_bias;
static void portapack_ui_set_antenna_bias(bool 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;
label_point.x -= 0;
label_point.y -= 16;
const char* s = "HRF";
switch(source) {
case CLOCK_SOURCE_EXTERNAL: { s = "EXT"; break; }
case CLOCK_SOURCE_PORTAPACK: { s = "PPK"; break; }
switch (source) {
case CLOCK_SOURCE_EXTERNAL: {
s = "EXT";
break;
}
case CLOCK_SOURCE_PORTAPACK: {
s = "PPK";
break;
}
default:
case CLOCK_SOURCE_HACKRF: { s = "HRF"; break; }
case CLOCK_SOURCE_HACKRF: {
s = "HRF";
break;
}
}
portapack_lcd_draw_string(label_point, s);
}
static void portapack_ui_set_transceiver_mode(transceiver_mode_t mode) {
(void)mode;
static void portapack_ui_set_transceiver_mode(transceiver_mode_t mode)
{
(void) mode;
}
static bool portapack_ui_operacake_gpio_compatible(void) {
static bool portapack_ui_operacake_gpio_compatible(void)
{
return false;
}
@ -581,8 +735,9 @@ const hackrf_ui_t portapack_hackrf_ui = {
&portapack_ui_operacake_gpio_compatible,
};
const hackrf_ui_t* portapack_hackrf_ui_init() {
if( portapack() ) {
const hackrf_ui_t* portapack_hackrf_ui_init()
{
if (portapack()) {
return &portapack_hackrf_ui;
} else {
return NULL;

View File

@ -26,4 +26,4 @@
const hackrf_ui_t* portapack_hackrf_ui_init() __attribute__((weak));
#endif/*__UI_PORTAPACK_H__*/
#endif /*__UI_PORTAPACK_H__*/

View File

@ -41,14 +41,14 @@ static bool lna_on = false;
static transceiver_mode_t trx_mode;
static bool enabled = false;
#define BLACK 0b00000000
#define RED 0b11100000
#define RED_DARK 0b01100000
#define GREEN 0b00011100
#define BLACK 0b00000000
#define RED 0b11100000
#define RED_DARK 0b01100000
#define GREEN 0b00011100
#define GREEN_DARK 0b00001100
#define BLUE 0b00000011
#define WHITE 0b11111111
#define GREY 0b01001101
#define BLUE 0b00000011
#define WHITE 0b11111111
#define GREY 0b01001101
static void draw_frequency(void)
{
@ -61,7 +61,7 @@ static void draw_frequency(void)
rad1o_setTextColor(BLACK, GREEN);
rad1o_setIntFont(&Font_Ubuntu18pt);
sprintf(tmp, "%4u.%03u", (unsigned int)mhz, (unsigned int)khz);
sprintf(tmp, "%4u.%03u", (unsigned int) mhz, (unsigned int) khz);
rad1o_lcdPrint(tmp);
rad1o_setIntFont(&Font_7x8);
@ -148,7 +148,7 @@ static void ui_update(void)
rad1o_lcdPrint("Rate: ");
mhz = sample_rate / 1000000;
khz = (sample_rate - mhz * 1000000) / 1000;
sprintf(tmp, "%2u.%03u MHz", (unsigned int)mhz, (unsigned int)khz);
sprintf(tmp, "%2u.%03u MHz", (unsigned int) mhz, (unsigned int) khz);
rad1o_lcdPrint(tmp);
rad1o_lcdNl();
@ -156,7 +156,7 @@ static void ui_update(void)
rad1o_lcdPrint("Filter: ");
mhz = filter_bw / 1000000;
khz = (filter_bw - mhz * 1000000) / 1000;
sprintf(tmp, "%2u.%03u MHz", (unsigned int)mhz, (unsigned int)khz);
sprintf(tmp, "%2u.%03u MHz", (unsigned int) mhz, (unsigned int) khz);
rad1o_lcdPrint(tmp);
rad1o_lcdNl();
@ -181,7 +181,7 @@ static void ui_update(void)
if (direction == RF_PATH_DIRECTION_TX) {
rad1o_setTextColor(BLACK, RED);
}
sprintf(tmp, " TX: %u dB", (unsigned int)bbtxvga_gain);
sprintf(tmp, " TX: %u dB", (unsigned int) bbtxvga_gain);
rad1o_lcdPrint(tmp);
rad1o_lcdNl();
@ -190,11 +190,11 @@ static void ui_update(void)
if (direction == RF_PATH_DIRECTION_RX) {
rad1o_setTextColor(BLACK, GREEN);
}
sprintf(tmp, "LNA: %2u dB", (unsigned int)bblna_gain);
sprintf(tmp, "LNA: %2u dB", (unsigned int) bblna_gain);
rad1o_lcdPrint(tmp);
rad1o_lcdNl();
rad1o_lcdMoveCrsr(2, 0);
sprintf(tmp, "VGA: %2u dB", (unsigned int)bbvga_gain);
sprintf(tmp, "VGA: %2u dB", (unsigned int) bbvga_gain);
rad1o_lcdPrint(tmp);
rad1o_lcdNl();
@ -277,8 +277,7 @@ static void rad1o_ui_set_first_if_frequency(const uint64_t frequency
// Not implemented
}
static void rad1o_ui_set_filter(const rf_path_filter_t filter
__attribute__((unused)))
static void rad1o_ui_set_filter(const rf_path_filter_t filter __attribute__((unused)))
{
// Not implemented
}
@ -288,8 +287,7 @@ static void rad1o_ui_set_antenna_bias(bool antenna_bias __attribute__((unused)))
// Not implemented
}
static void rad1o_ui_set_clock_source(clock_source_t source
__attribute__((unused)))
static void rad1o_ui_set_clock_source(clock_source_t source __attribute__((unused)))
{
// Not implemented
}
@ -324,7 +322,7 @@ static const hackrf_ui_t rad1o_ui = {
&rad1o_ui_operacake_gpio_compatible,
};
const hackrf_ui_t *rad1o_ui_setup(void)
const hackrf_ui_t* rad1o_ui_setup(void)
{
return &rad1o_ui;
}

View File

@ -24,6 +24,6 @@
#include "hackrf_ui.h"
const hackrf_ui_t *rad1o_ui_setup(void) __attribute__((weak));
const hackrf_ui_t* rad1o_ui_setup(void) __attribute__((weak));
#endif /*__UI_RAD1O_H__*/

View File

@ -36,47 +36,51 @@ usb_device_t* usb_device_usb0 = 0;
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(
const uint_fast8_t endpoint_address
) {
usb_queue_head_t* usb_queue_head(const uint_fast8_t endpoint_address)
{
return &usb_qh[USB_QH_INDEX(endpoint_address)];
}
usb_endpoint_t* usb_endpoint_from_address(
const uint_fast8_t endpoint_address
) {
return (usb_endpoint_t*)usb_queue_head(endpoint_address)->_reserved_0;
usb_endpoint_t* usb_endpoint_from_address(const uint_fast8_t endpoint_address)
{
return (usb_endpoint_t*) usb_queue_head(endpoint_address)->_reserved_0;
}
static uint_fast8_t usb_endpoint_address(
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;
}
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;
}
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);
}
void usb_peripheral_reset() {
void usb_peripheral_reset()
{
RESET_CTRL0 = RESET_CTRL0_USB0_RST;
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;
}
static void usb_clear_pending_interrupts(const uint32_t mask) {
static void usb_clear_pending_interrupts(const uint32_t mask)
{
USB0_ENDPTNAK = mask;
USB0_ENDPTNAKEN = mask;
USB0_USBSTS_D = mask;
@ -84,117 +88,118 @@ static void usb_clear_pending_interrupts(const uint32_t 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);
}
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
// 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
// will continue until completion.
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
// 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_flush_endpoints(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);
}
static void usb_endpoint_set_type(
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
// that the disabled side of an endpoint must be set to a non-control type
// (e.g. bulk, interrupt, or iso).
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
USB0_ENDPTCTRL(endpoint_number)
= ( USB0_ENDPTCTRL(endpoint_number)
& ~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)
)
| ( USB0_ENDPTCTRL_TXT1_0(transfer_type)
| USB0_ENDPTCTRL_RXT(transfer_type)
);
USB0_ENDPTCTRL(endpoint_number) =
(USB0_ENDPTCTRL(endpoint_number) &
~(USB0_ENDPTCTRL_TXT1_0_MASK | USB0_ENDPTCTRL_RXT_MASK)) |
(USB0_ENDPTCTRL_TXT1_0(transfer_type) |
USB0_ENDPTCTRL_RXT(transfer_type));
}
static void usb_endpoint_enable(
const usb_endpoint_t* const endpoint
) {
static void usb_endpoint_enable(const usb_endpoint_t* const endpoint)
{
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR);
if (usb_endpoint_is_in(endpoint->address)) {
USB0_ENDPTCTRL(endpoint_number) |=
(USB0_ENDPTCTRL_TXE | USB0_ENDPTCTRL_TXR);
} 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(
const usb_endpoint_t* const endpoint
) {
static void usb_endpoint_clear_pending_interrupts(const usb_endpoint_t* const endpoint)
{
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
if( usb_endpoint_is_in(endpoint->address) ) {
usb_clear_pending_interrupts(USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number));
if (usb_endpoint_is_in(endpoint->address)) {
usb_clear_pending_interrupts(
USB0_ENDPTCOMPLETE_ETCE(1 << endpoint_number));
} 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(
const usb_endpoint_t* const endpoint
) {
void usb_endpoint_disable(const usb_endpoint_t* const endpoint)
{
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);
} else {
USB0_ENDPTCTRL(endpoint_number) &= ~(USB0_ENDPTCTRL_RXE);
}
usb_queue_flush_endpoint(endpoint);
usb_queue_flush_endpoint(endpoint);
usb_endpoint_clear_pending_interrupts(endpoint);
usb_endpoint_flush(endpoint);
}
void usb_endpoint_prime(
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);
qh->next_dtd_pointer = first_td;
qh->total_bytes
&= ~( USB_TD_DTD_TOKEN_STATUS_ACTIVE
| USB_TD_DTD_TOKEN_STATUS_HALTED
)
;
qh->total_bytes &=
~(USB_TD_DTD_TOKEN_STATUS_ACTIVE | USB_TD_DTD_TOKEN_STATUS_HALTED);
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_ENDPTPRIME = USB0_ENDPTPRIME_PETB(1 << endpoint_number);
} else {
USB0_ENDPTPRIME = USB0_ENDPTPRIME_PERB(1 << endpoint_number);
}
}
static bool usb_endpoint_is_priming(
const usb_endpoint_t* const endpoint
) {
static bool usb_endpoint_is_priming(const usb_endpoint_t* const endpoint)
{
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);
} else {
return USB0_ENDPTPRIME & USB0_ENDPTPRIME_PERB(1 << endpoint_number);
@ -205,12 +210,12 @@ static bool usb_endpoint_is_priming(
// the given endpoint, waiting until the endpoint has finished.
void usb_endpoint_schedule_wait(
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.
// It may have been flushed due to an aborted transaction.
// 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;
@ -225,8 +230,8 @@ void usb_endpoint_schedule_wait(
void usb_endpoint_schedule_append(
const usb_endpoint_t* const endpoint,
usb_transfer_descriptor_t* const tail_td,
usb_transfer_descriptor_t* const new_td
) {
usb_transfer_descriptor_t* const new_td)
{
bool done;
tail_td->next_dtd_pointer = new_td;
@ -241,22 +246,22 @@ void usb_endpoint_schedule_append(
} while (!(USB0_USBCMD_D & USB0_USBCMD_D_ATDTW));
USB0_USBCMD_D &= ~USB0_USBCMD_D_ATDTW;
if(!done) {
if (!done) {
usb_endpoint_prime(endpoint, new_td);
}
}
void usb_endpoint_flush(
const usb_endpoint_t* const endpoint
) {
void usb_endpoint_flush(const usb_endpoint_t* const endpoint)
{
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
usb_queue_flush_endpoint(endpoint);
if( usb_endpoint_is_in(endpoint->address) ) {
if (usb_endpoint_is_in(endpoint->address)) {
usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FETB(1 << endpoint_number));
} else {
usb_flush_primed_endpoints(USB0_ENDPTFLUSH_FERB(1 << endpoint_number));
}
}
/*
static bool usb_endpoint_is_flushing(
const usb_endpoint_t* const endpoint
@ -269,82 +274,81 @@ static bool usb_endpoint_is_flushing(
}
}
*/
bool usb_endpoint_is_ready(
const usb_endpoint_t* const endpoint
) {
bool usb_endpoint_is_ready(const usb_endpoint_t* const endpoint)
{
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);
} else {
return USB0_ENDPTSTAT & USB0_ENDPTSTAT_ERBR(1 << endpoint_number);
}
}
bool usb_endpoint_is_complete(
const usb_endpoint_t* const endpoint
) {
bool usb_endpoint_is_complete(const usb_endpoint_t* const endpoint)
{
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);
} else {
return USB0_ENDPTCOMPLETE & USB0_ENDPTCOMPLETE_ERCE(1 << endpoint_number);
}
}
void usb_endpoint_stall(
const usb_endpoint_t* const endpoint
) {
void usb_endpoint_stall(const usb_endpoint_t* const endpoint)
{
// Endpoint is to be stalled as a pair -- both OUT and IN.
// See UM10503 section 23.10.5.2 "Stalling"
const uint_fast8_t endpoint_number = usb_endpoint_number(endpoint->address);
USB0_ENDPTCTRL(endpoint_number) |= (USB0_ENDPTCTRL_RXS | USB0_ENDPTCTRL_TXS);
// TODO: Also need to reset data toggle in both directions?
}
void usb_endpoint_reset_data_toggle(
const usb_endpoint_t* const endpoint
) {
void usb_endpoint_reset_data_toggle(const usb_endpoint_t* const endpoint)
{
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;
} else {
USB0_ENDPTCTRL(endpoint_number) |= USB0_ENDPTCTRL_RXR;
}
}
static void usb_controller_run() {
static void usb_controller_run()
{
USB0_USBCMD_D |= USB0_USBCMD_D_RS;
}
static void usb_controller_stop() {
static void usb_controller_stop()
{
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;
}
static void usb_controller_set_device_mode() {
static void usb_controller_set_device_mode()
{
// Set USB0 peripheral mode
USB0_USBMODE_D = USB0_USBMODE_D_CM1_0(2);
// Set device-related OTG flags
// OTG termination: controls pull-down on USB_DM
USB0_OTGSC = USB0_OTGSC_OT;
}
usb_speed_t usb_speed(
const usb_device_t* const device
) {
if( device == usb_device_usb0 ) {
switch( USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK ) {
usb_speed_t usb_speed(const usb_device_t* const device)
{
if (device == usb_device_usb0) {
switch (USB0_PORTSC1_D & USB0_PORTSC1_D_PSPD_MASK) {
case USB0_PORTSC1_D_PSPD(0):
return USB_SPEED_FULL;
case USB0_PORTSC1_D_PSPD(2):
return USB_SPEED_HIGH;
default:
// TODO: What to do/return here? Is this even possible?
return USB_SPEED_FULL;
@ -356,39 +360,46 @@ 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;
}
static uint32_t usb_get_status() {
// Mask status flags with enabled flag interrupts.
static uint32_t usb_get_status()
{
// Mask status flags with enabled flag interrupts.
const uint32_t status = USB0_USBSTS_D & USB0_USBINTR_D;
// Clear flags that were just read, leaving alone any flags that
// were just set (after the read). It's important to read and
// reset flags atomically! :-)
// Clear flags that were just read, leaving alone any flags that
// were just set (after the read). It's important to read and
// reset flags atomically! :-)
usb_clear_status(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;
}
static uint32_t usb_get_endpoint_setup_status() {
return USB0_ENDPTSETUPSTAT;
static uint32_t usb_get_endpoint_setup_status()
{
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;
}
static uint32_t usb_get_endpoint_complete() {
static uint32_t usb_get_endpoint_complete()
{
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?
USB0_ENDPTCTRL0 &= ~(USB0_ENDPTCTRL0_RXE | USB0_ENDPTCTRL0_TXE);
USB0_ENDPTCTRL1 &= ~(USB0_ENDPTCTRL1_RXE | USB0_ENDPTCTRL1_TXE);
@ -400,32 +411,30 @@ static void usb_disable_all_endpoints() {
void usb_set_address_immediate(
const usb_device_t* const device,
const uint_fast8_t address
) {
if( device == usb_device_usb0 ) {
const uint_fast8_t address)
{
if (device == usb_device_usb0) {
USB0_DEVICEADDR = USB0_DEVICEADDR_USBADR(address);
}
}
void usb_set_address_deferred(
const usb_device_t* const device,
const uint_fast8_t address
) {
if( device == usb_device_usb0 ) {
USB0_DEVICEADDR
= USB0_DEVICEADDR_USBADR(address)
| USB0_DEVICEADDR_USBADRA
;
void usb_set_address_deferred(const usb_device_t* const device, const uint_fast8_t address)
{
if (device == usb_device_usb0) {
USB0_DEVICEADDR =
USB0_DEVICEADDR_USBADR(address) | USB0_DEVICEADDR_USBADRA;
}
}
static void usb_reset_all_endpoints() {
static void usb_reset_all_endpoints()
{
usb_disable_all_endpoints();
usb_clear_all_pending_interrupts();
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
// new endpoints before the controller is reset?
usb_reset_all_endpoints();
@ -437,15 +446,16 @@ static void usb_controller_reset() {
// all primed endpoints and stopping controller.
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":
usb_reset_all_endpoints();
usb_set_address_immediate(device, 0);
usb_set_configuration(device, 0);
// TODO: Enable endpoint 0, which might not actually be necessary,
// as the datasheet claims it can't be disabled.
@ -458,37 +468,32 @@ static void usb_bus_reset(usb_device_t* const device) {
//}
}
static void usb_interrupt_enable(
usb_device_t* const device
) {
if( device == usb_device_usb0 ) {
static void usb_interrupt_enable(usb_device_t* const device)
{
if (device == usb_device_usb0) {
nvic_enable_irq(NVIC_USB0_IRQ);
}
}
void usb_device_init(
const uint_fast8_t device_ordinal,
usb_device_t* const device
) {
if( device_ordinal == 0 ) {
void usb_device_init(const uint_fast8_t device_ordinal, usb_device_t* const device)
{
if (device_ordinal == 0) {
usb_device_usb0 = device;
usb_phy_enable();
usb_controller_reset();
usb_controller_set_device_mode();
// Set interrupt threshold interval to 0
USB0_USBCMD_D &= ~USB0_USBCMD_D_ITC_MASK;
// Configure endpoint list address
USB0_ENDPOINTLISTADDR = (uint32_t)usb_qh;
// Configure endpoint list address
USB0_ENDPOINTLISTADDR = (uint32_t) usb_qh;
// Enable interrupts
USB0_USBINTR_D =
USB0_USBINTR_D_UE
| USB0_USBINTR_D_UEE
| USB0_USBINTR_D_PCE
| USB0_USBINTR_D_URE
USB0_USBINTR_D = USB0_USBINTR_D_UE | USB0_USBINTR_D_UEE |
USB0_USBINTR_D_PCE |
USB0_USBINTR_D_URE
//| USB0_USBINTR_D_SRE
| USB0_USBINTR_D_SLE
//| USB0_USBINTR_D_NAKE
@ -496,14 +501,14 @@ void usb_device_init(
}
}
void usb_run(
usb_device_t* const device
) {
void usb_run(usb_device_t* const device)
{
usb_interrupt_enable(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 = src[1];
dst->value_l = src[2];
@ -514,102 +519,108 @@ static void copy_setup(usb_setup_t* const dst, const volatile uint8_t* const src
dst->length_h = src[7];
}
void usb_endpoint_init(
const usb_endpoint_t* const endpoint
) {
void usb_endpoint_init(const usb_endpoint_t* const endpoint)
{
usb_endpoint_flush(endpoint);
uint_fast16_t max_packet_size = endpoint->device->descriptor[7];
usb_transfer_type_t transfer_type = USB_TRANSFER_TYPE_CONTROL;
const uint8_t* const endpoint_descriptor = usb_endpoint_descriptor(endpoint);
if( endpoint_descriptor ) {
max_packet_size = usb_endpoint_descriptor_max_packet_size(endpoint_descriptor);
transfer_type = usb_endpoint_descriptor_transfer_type(endpoint_descriptor);
if (endpoint_descriptor) {
max_packet_size =
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
// descriptor.
usb_queue_head_t* const qh = usb_queue_head(endpoint->address);
qh->capabilities
= USB_QH_CAPABILITIES_MULT(0)
| USB_QH_CAPABILITIES_ZLT
| USB_QH_CAPABILITIES_MPL(max_packet_size)
| ((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS : 0)
;
qh->capabilities = USB_QH_CAPABILITIES_MULT(0) | USB_QH_CAPABILITIES_ZLT |
USB_QH_CAPABILITIES_MPL(max_packet_size) |
((transfer_type == USB_TRANSFER_TYPE_CONTROL) ? USB_QH_CAPABILITIES_IOS :
0);
qh->current_dtd_pointer = 0;
qh->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
qh->total_bytes
= USB_TD_DTD_TOKEN_TOTAL_BYTES(0)
| USB_TD_DTD_TOKEN_MULTO(0)
;
qh->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(0) | USB_TD_DTD_TOKEN_MULTO(0);
qh->buffer_pointer_page[0] = 0;
qh->buffer_pointer_page[1] = 0;
qh->buffer_pointer_page[2] = 0;
qh->buffer_pointer_page[3] = 0;
qh->buffer_pointer_page[4] = 0;
// This is how we look up an endpoint structure from an endpoint address:
qh->_reserved_0 = (uint32_t)endpoint;
qh->_reserved_0 = (uint32_t) endpoint;
// TODO: Should NAK be enabled? I'm kinda squishy on this...
//USB0_ENDPTNAKEN |=
// USB0_ENDPTNAKEN_EPRNE(1 << endpoint_out->number);
usb_endpoint_set_type(endpoint, transfer_type);
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();
if( endptsetupstat ) {
for( uint_fast8_t i=0; i<6; i++ ) {
const uint32_t endptsetupstat_bit = USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i);
if( endptsetupstat & endptsetupstat_bit ) {
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
);
if( endpoint && endpoint->setup_complete ) {
copy_setup(&endpoint->setup, usb_queue_head(endpoint->address)->setup);
if (endptsetupstat) {
for (uint_fast8_t i = 0; i < 6; i++) {
const uint32_t endptsetupstat_bit =
USB0_ENDPTSETUPSTAT_ENDPTSETUPSTAT(1 << i);
if (endptsetupstat & endptsetupstat_bit) {
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(usb_endpoint_address(
USB_TRANSFER_DIRECTION_OUT,
i));
if (endpoint && endpoint->setup_complete) {
copy_setup(
&endpoint->setup,
usb_queue_head(endpoint->address)->setup);
// TODO: Clean up this duplicated effort by providing
// a cleaner way to get the SETUP data.
copy_setup(&endpoint->in->setup, usb_queue_head(endpoint->address)->setup);
usb_clear_endpoint_setup_status(endptsetupstat_bit);
copy_setup(
&endpoint->in->setup,
usb_queue_head(endpoint->address)->setup);
usb_clear_endpoint_setup_status(
endptsetupstat_bit);
endpoint->setup_complete(endpoint);
} 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();
if( endptcomplete ) {
for( uint_fast8_t i=0; i<6; i++ ) {
const uint32_t endptcomplete_out_bit = USB0_ENDPTCOMPLETE_ERCE(1 << i);
if( endptcomplete & endptcomplete_out_bit ) {
if (endptcomplete) {
for (uint_fast8_t i = 0; i < 6; i++) {
const uint32_t endptcomplete_out_bit =
USB0_ENDPTCOMPLETE_ERCE(1 << i);
if (endptcomplete & endptcomplete_out_bit) {
usb_clear_endpoint_complete(endptcomplete_out_bit);
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_OUT, i)
);
if( endpoint && endpoint->transfer_complete ) {
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(usb_endpoint_address(
USB_TRANSFER_DIRECTION_OUT,
i));
if (endpoint && endpoint->transfer_complete) {
endpoint->transfer_complete(endpoint);
}
}
const uint32_t endptcomplete_in_bit = USB0_ENDPTCOMPLETE_ETCE(1 << i);
if( endptcomplete & endptcomplete_in_bit ) {
const uint32_t endptcomplete_in_bit =
USB0_ENDPTCOMPLETE_ETCE(1 << i);
if (endptcomplete & endptcomplete_in_bit) {
usb_clear_endpoint_complete(endptcomplete_in_bit);
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(
usb_endpoint_address(USB_TRANSFER_DIRECTION_IN, i)
);
if( endpoint && endpoint->transfer_complete ) {
usb_endpoint_t* const endpoint =
usb_endpoint_from_address(usb_endpoint_address(
USB_TRANSFER_DIRECTION_IN,
i));
if (endpoint && endpoint->transfer_complete) {
endpoint->transfer_complete(endpoint);
}
}
@ -617,15 +628,16 @@ static void usb_check_for_transfer_events() {
}
}
void usb0_isr() {
void usb0_isr()
{
const uint32_t status = usb_get_status();
if( status == 0 ) {
if (status == 0) {
// Nothing to do.
return;
}
if( status & USB0_USBSTS_D_UI ) {
if (status & USB0_USBSTS_D_UI) {
// USB:
// - Completed transaction transfer descriptor has IOC set.
// - Short packet detected.
@ -633,29 +645,29 @@ void usb0_isr() {
usb_check_for_setup_events();
usb_check_for_transfer_events();
// TODO: Reset ignored ENDPTSETUPSTAT and ENDPTCOMPLETE flags?
}
if( status & USB0_USBSTS_D_SRI ) {
if (status & USB0_USBSTS_D_SRI) {
// Start Of Frame received.
}
if( status & USB0_USBSTS_D_PCI ) {
if (status & USB0_USBSTS_D_PCI) {
// Port change detect:
// Port controller entered full- or high-speed operational state.
}
if( status & USB0_USBSTS_D_SLI ) {
if (status & USB0_USBSTS_D_SLI) {
// Device controller suspend.
}
if( status & USB0_USBSTS_D_URI ) {
if (status & USB0_USBSTS_D_URI) {
// USB reset received.
usb_bus_reset(usb_device_usb0);
}
if( status & USB0_USBSTS_D_UEI ) {
if (status & USB0_USBSTS_D_UEI) {
// USB error:
// Completion of a USB transaction resulted in an error condition.
// Set along with USBINT if the TD on which the error interrupt
@ -663,7 +675,7 @@ void usb0_isr() {
// The device controller detects resume signalling only.
}
if( status & USB0_USBSTS_D_NAKI ) {
if (status & USB0_USBSTS_D_NAKI) {
// Both the TX/RX endpoint NAK bit and corresponding TX/RX endpoint
// NAK enable bit are set.
}

View File

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

View File

@ -33,195 +33,210 @@
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(
const usb_endpoint_t* const endpoint
) {
uint32_t index = USB_ENDPOINT_INDEX(endpoint->address);
if (endpoint_queues[index] == NULL) while (1);
return endpoint_queues[index];
static usb_queue_t* endpoint_queue(const usb_endpoint_t* const endpoint)
{
uint32_t index = USB_ENDPOINT_INDEX(endpoint->address);
if (endpoint_queues[index] == NULL) {
while (1) {}
}
return endpoint_queues[index];
}
void usb_queue_init(
usb_queue_t* const queue
) {
uint32_t index = USB_ENDPOINT_INDEX(queue->endpoint->address);
if (endpoint_queues[index] != NULL) while (1);
endpoint_queues[index] = queue;
void usb_queue_init(usb_queue_t* const queue)
{
uint32_t index = USB_ENDPOINT_INDEX(queue->endpoint->address);
if (endpoint_queues[index] != NULL) {
while (1) {}
}
endpoint_queues[index] = queue;
usb_transfer_t* t = queue->free_transfers;
for (unsigned int i=0; i < queue->pool_size - 1; i++, t++) {
t->next = t+1;
t->queue = queue;
}
t->next = NULL;
t->queue = queue;
usb_transfer_t* t = queue->free_transfers;
for (unsigned int i = 0; i < queue->pool_size - 1; i++, t++) {
t->next = t + 1;
t->queue = queue;
}
t->next = NULL;
t->queue = queue;
}
/* Allocate a transfer */
static usb_transfer_t* allocate_transfer(
usb_queue_t* const queue
) {
bool aborted;
usb_transfer_t* transfer;
if (queue->free_transfers == NULL)
return NULL;
static usb_transfer_t* allocate_transfer(usb_queue_t* const queue)
{
bool aborted;
usb_transfer_t* transfer;
if (queue->free_transfers == NULL) {
return NULL;
}
do {
transfer = (void *) __ldrex((uint32_t *) &queue->free_transfers);
aborted = __strex((uint32_t) transfer->next, (uint32_t *) &queue->free_transfers);
} while (aborted);
transfer->next = NULL;
return transfer;
do {
transfer = (void*) __ldrex((uint32_t*) &queue->free_transfers);
aborted =
__strex((uint32_t) transfer->next,
(uint32_t*) &queue->free_transfers);
} while (aborted);
transfer->next = NULL;
return transfer;
}
/* Place a transfer in the free list */
static void free_transfer(usb_transfer_t* const transfer)
{
usb_queue_t* const queue = transfer->queue;
bool aborted;
do {
transfer->next = (void *) __ldrex((uint32_t *) &queue->free_transfers);
aborted = __strex((uint32_t) transfer, (uint32_t *) &queue->free_transfers);
} while (aborted);
usb_queue_t* const queue = transfer->queue;
bool aborted;
do {
transfer->next = (void*) __ldrex((uint32_t*) &queue->free_transfers);
aborted =
__strex((uint32_t) transfer, (uint32_t*) &queue->free_transfers);
} while (aborted);
}
/* Add a transfer to the end of an endpoint's queue. Returns the old
* tail or NULL is the queue was empty
*/
static usb_transfer_t* endpoint_queue_transfer(
usb_transfer_t* const transfer
) {
usb_queue_t* const queue = transfer->queue;
transfer->next = NULL;
if (queue->active != NULL) {
usb_transfer_t* t = queue->active;
while (t->next != NULL) t = t->next;
t->next = transfer;
return t;
} else {
queue->active = transfer;
return NULL;
}
static usb_transfer_t* endpoint_queue_transfer(usb_transfer_t* const transfer)
{
usb_queue_t* const queue = transfer->queue;
transfer->next = NULL;
if (queue->active != NULL) {
usb_transfer_t* t = queue->active;
while (t->next != NULL) {
t = t->next;
}
t->next = transfer;
return t;
} else {
queue->active = transfer;
return NULL;
}
}
static void usb_queue_flush_queue(usb_queue_t* const queue)
{
cm_disable_interrupts();
while (queue->active) {
usb_transfer_t* transfer = queue->active;
queue->active = transfer->next;
free_transfer(transfer);
}
cm_enable_interrupts();
cm_disable_interrupts();
while (queue->active) {
usb_transfer_t* transfer = queue->active;
queue->active = transfer->next;
free_transfer(transfer);
}
cm_enable_interrupts();
}
void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint)
{
usb_queue_flush_queue(endpoint_queue(endpoint));
usb_queue_flush_queue(endpoint_queue(endpoint));
}
int usb_transfer_schedule(
const usb_endpoint_t* const endpoint,
void* const data,
const uint32_t maximum_length,
const transfer_completion_cb completion_cb,
void* const user_data
) {
usb_queue_t* const queue = endpoint_queue(endpoint);
usb_transfer_t* const transfer = allocate_transfer(queue);
if (transfer == NULL) return -1;
usb_transfer_descriptor_t* const td = &transfer->td;
const transfer_completion_cb completion_cb,
void* const user_data)
{
usb_queue_t* const queue = endpoint_queue(endpoint);
usb_transfer_t* const transfer = allocate_transfer(queue);
if (transfer == NULL) {
return -1;
}
usb_transfer_descriptor_t* const td = &transfer->td;
// Configure the transfer descriptor
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
td->total_bytes =
USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length)
| USB_TD_DTD_TOKEN_IOC
| USB_TD_DTD_TOKEN_MULTO(0)
| USB_TD_DTD_TOKEN_STATUS_ACTIVE
;
td->buffer_pointer_page[0] = (uint32_t)data;
td->buffer_pointer_page[1] = ((uint32_t)data + 0x1000) & 0xfffff000;
td->buffer_pointer_page[2] = ((uint32_t)data + 0x2000) & 0xfffff000;
td->buffer_pointer_page[3] = ((uint32_t)data + 0x3000) & 0xfffff000;
td->buffer_pointer_page[4] = ((uint32_t)data + 0x4000) & 0xfffff000;
td->next_dtd_pointer = USB_TD_NEXT_DTD_POINTER_TERMINATE;
td->total_bytes = USB_TD_DTD_TOKEN_TOTAL_BYTES(maximum_length) |
USB_TD_DTD_TOKEN_IOC | USB_TD_DTD_TOKEN_MULTO(0) |
USB_TD_DTD_TOKEN_STATUS_ACTIVE;
td->buffer_pointer_page[0] = (uint32_t) data;
td->buffer_pointer_page[1] = ((uint32_t) data + 0x1000) & 0xfffff000;
td->buffer_pointer_page[2] = ((uint32_t) data + 0x2000) & 0xfffff000;
td->buffer_pointer_page[3] = ((uint32_t) data + 0x3000) & 0xfffff000;
td->buffer_pointer_page[4] = ((uint32_t) data + 0x4000) & 0xfffff000;
// Fill in transfer fields
transfer->maximum_length = maximum_length;
transfer->completion_cb = completion_cb;
transfer->user_data = user_data;
// Fill in transfer fields
transfer->maximum_length = maximum_length;
transfer->completion_cb = completion_cb;
transfer->user_data = user_data;
cm_disable_interrupts();
usb_transfer_t* tail = endpoint_queue_transfer(transfer);
if (tail == NULL) {
// The queue is currently empty, we need to re-prime
usb_endpoint_schedule_wait(queue->endpoint, &transfer->td);
} else {
// The queue is currently running, try to append
usb_endpoint_schedule_append(queue->endpoint, &tail->td, &transfer->td);
}
cm_enable_interrupts();
return 0;
cm_disable_interrupts();
usb_transfer_t* tail = endpoint_queue_transfer(transfer);
if (tail == NULL) {
// The queue is currently empty, we need to re-prime
usb_endpoint_schedule_wait(queue->endpoint, &transfer->td);
} else {
// The queue is currently running, try to append
usb_endpoint_schedule_append(queue->endpoint, &tail->td, &transfer->td);
}
cm_enable_interrupts();
return 0;
}
int usb_transfer_schedule_block(
const usb_endpoint_t* const endpoint,
void* const data,
const uint32_t maximum_length,
const transfer_completion_cb completion_cb,
void* const user_data
) {
int ret;
do {
ret = usb_transfer_schedule(endpoint, data, maximum_length,
completion_cb, user_data);
} while (ret == -1);
return 0;
const transfer_completion_cb completion_cb,
void* const user_data)
{
int ret;
do {
ret = usb_transfer_schedule(
endpoint,
data,
maximum_length,
completion_cb,
user_data);
} while (ret == -1);
return 0;
}
int usb_transfer_schedule_ack(
const usb_endpoint_t* const endpoint
) {
return usb_transfer_schedule_block(endpoint, 0, 0, NULL, NULL);
int usb_transfer_schedule_ack(const usb_endpoint_t* const endpoint)
{
return usb_transfer_schedule_block(endpoint, 0, 0, NULL, NULL);
}
/* Called when an endpoint might have completed a transfer */
void usb_queue_transfer_complete(usb_endpoint_t* const endpoint)
{
usb_queue_t* const queue = endpoint_queue(endpoint);
if (queue == NULL) while(1); // Uh oh
usb_transfer_t* transfer = queue->active;
usb_queue_t* const queue = endpoint_queue(endpoint);
if (queue == NULL) {
while (1) {} // Uh oh
}
usb_transfer_t* transfer = queue->active;
while (transfer != NULL) {
uint8_t status = transfer->td.total_bytes;
while (transfer != NULL) {
uint8_t status = transfer->td.total_bytes;
// Check for failures
if ( status & USB_TD_DTD_TOKEN_STATUS_HALTED
|| status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR
|| status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) {
// TODO: Uh oh, do something useful here
while (1);
}
// Check for failures
if (status & USB_TD_DTD_TOKEN_STATUS_HALTED ||
status & USB_TD_DTD_TOKEN_STATUS_BUFFER_ERROR ||
status & USB_TD_DTD_TOKEN_STATUS_TRANSACTION_ERROR) {
// TODO: Uh oh, do something useful here
while (1) {}
}
// Still not finished
if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE)
break;
// Still not finished
if (status & USB_TD_DTD_TOKEN_STATUS_ACTIVE) {
break;
}
// Advance the head. We need to do this before invoking the completion
// callback as it might attempt to schedule a new transfer
queue->active = transfer->next;
usb_transfer_t* next = transfer->next;
// Advance the head. We need to do this before invoking the completion
// callback as it might attempt to schedule a new transfer
queue->active = transfer->next;
usb_transfer_t* next = transfer->next;
// 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 transferred = transfer->maximum_length - total_bytes;
if (transfer->completion_cb)
transfer->completion_cb(transfer->user_data, transferred);
// 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 transferred = transfer->maximum_length - total_bytes;
if (transfer->completion_cb) {
transfer->completion_cb(transfer->user_data, transferred);
}
// Advance head and free transfer
free_transfer(transfer);
transfer = next;
}
// Advance head and free transfer
free_transfer(transfer);
transfer = next;
}
}

View File

@ -33,31 +33,29 @@ typedef void (*transfer_completion_cb)(void*, unsigned int);
// This is an opaque datatype. Thou shall not touch these members.
struct _usb_transfer_t {
struct _usb_transfer_t* next;
usb_transfer_descriptor_t td ATTR_ALIGNED(64);
unsigned int maximum_length;
struct _usb_queue_t* queue;
transfer_completion_cb completion_cb;
void* user_data;
struct _usb_transfer_t* next;
usb_transfer_descriptor_t td ATTR_ALIGNED(64);
unsigned int maximum_length;
struct _usb_queue_t* queue;
transfer_completion_cb completion_cb;
void* user_data;
};
// This is an opaque datatype. Thou shall not touch these members.
struct _usb_queue_t {
struct usb_endpoint_t* endpoint;
const unsigned int pool_size;
usb_transfer_t* volatile free_transfers;
usb_transfer_t* volatile active;
struct usb_endpoint_t* endpoint;
const unsigned int pool_size;
usb_transfer_t* volatile free_transfers;
usb_transfer_t* volatile active;
};
#define USB_DECLARE_QUEUE(endpoint_name) \
struct _usb_queue_t endpoint_name##_queue;
#define USB_DEFINE_QUEUE(endpoint_name, _pool_size) \
struct _usb_transfer_t endpoint_name##_transfers[_pool_size]; \
struct _usb_queue_t endpoint_name##_queue = { \
.endpoint = &endpoint_name, \
.free_transfers = endpoint_name##_transfers, \
.pool_size = _pool_size \
};
#define USB_DECLARE_QUEUE(endpoint_name) struct _usb_queue_t endpoint_name##_queue;
#define USB_DEFINE_QUEUE(endpoint_name, _pool_size) \
struct _usb_transfer_t endpoint_name##_transfers[_pool_size]; \
struct _usb_queue_t endpoint_name##_queue = { \
.endpoint = &endpoint_name, \
.free_transfers = endpoint_name##_transfers, \
.pool_size = _pool_size};
void usb_queue_flush_endpoint(const usb_endpoint_t* const endpoint);
@ -65,28 +63,20 @@ int usb_transfer_schedule(
const usb_endpoint_t* const endpoint,
void* const data,
const uint32_t maximum_length,
const transfer_completion_cb completion_cb,
void* const user_data
);
const transfer_completion_cb completion_cb,
void* const user_data);
int usb_transfer_schedule_block(
const usb_endpoint_t* const endpoint,
void* const data,
const uint32_t maximum_length,
const transfer_completion_cb completion_cb,
void* const user_data
);
const transfer_completion_cb completion_cb,
void* const user_data);
int usb_transfer_schedule_ack(
const usb_endpoint_t* const endpoint
);
int usb_transfer_schedule_ack(const usb_endpoint_t* const endpoint);
void usb_queue_init(
usb_queue_t* const queue
);
void usb_queue_init(usb_queue_t* const queue);
void usb_queue_transfer_complete(
usb_endpoint_t* const endpoint
);
void usb_queue_transfer_complete(usb_endpoint_t* const endpoint);
#endif//__USB_QUEUE_H__
#endif //__USB_QUEUE_H__

View File

@ -25,70 +25,64 @@
#include <stdbool.h>
static void usb_request(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
static void usb_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
{
usb_request_status_t status = USB_REQUEST_STATUS_STALL;
usb_request_handler_fn handler = 0;
switch( endpoint->setup.request_type & USB_SETUP_REQUEST_TYPE_mask ) {
switch (endpoint->setup.request_type & USB_SETUP_REQUEST_TYPE_mask) {
case USB_SETUP_REQUEST_TYPE_STANDARD:
handler = usb_request_handlers.standard;
break;
case USB_SETUP_REQUEST_TYPE_CLASS:
handler = usb_request_handlers.class;
break;
case USB_SETUP_REQUEST_TYPE_VENDOR:
handler = usb_request_handlers.vendor;
break;
case USB_SETUP_REQUEST_TYPE_RESERVED:
handler = usb_request_handlers.reserved;
break;
}
if( handler ) {
if (handler) {
status = handler(endpoint, stage);
}
if( status != USB_REQUEST_STATUS_OK ) {
if (status != USB_REQUEST_STATUS_OK) {
// USB 2.0 section 9.2.7 "Request Error"
usb_endpoint_stall(endpoint);
}
}
void usb_setup_complete(
usb_endpoint_t* const endpoint
) {
void usb_setup_complete(usb_endpoint_t* const endpoint)
{
usb_request(endpoint, USB_TRANSFER_STAGE_SETUP);
}
void usb_control_out_complete(
usb_endpoint_t* const endpoint
) {
const bool device_to_host =
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if( device_to_host ) {
void usb_control_out_complete(usb_endpoint_t* const endpoint)
{
const bool device_to_host = endpoint->setup.request_type >>
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if (device_to_host) {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
} else {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
}
usb_queue_transfer_complete(endpoint);
usb_queue_transfer_complete(endpoint);
}
void usb_control_in_complete(
usb_endpoint_t* const endpoint
) {
const bool device_to_host =
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if( device_to_host ) {
void usb_control_in_complete(usb_endpoint_t* const endpoint)
{
const bool device_to_host = endpoint->setup.request_type >>
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
if (device_to_host) {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
} else {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
}
usb_queue_transfer_complete(endpoint);
usb_queue_transfer_complete(endpoint);
}

View File

@ -41,11 +41,10 @@ typedef enum {
USB_REQUEST_STATUS_OK = 0,
USB_REQUEST_STATUS_STALL = 1,
} usb_request_status_t;
typedef usb_request_status_t (*usb_request_handler_fn)(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
);
const usb_transfer_stage_t stage);
typedef struct {
usb_request_handler_fn standard;
@ -56,16 +55,10 @@ typedef struct {
extern const usb_request_handlers_t usb_request_handlers;
void usb_setup_complete(
usb_endpoint_t* const endpoint
);
void usb_setup_complete(usb_endpoint_t* const endpoint);
void usb_control_in_complete(
usb_endpoint_t* const endpoint
);
void usb_control_in_complete(usb_endpoint_t* const endpoint);
void usb_control_out_complete(
usb_endpoint_t* const endpoint
);
void usb_control_out_complete(usb_endpoint_t* const endpoint);
#endif//__USB_REQUEST_H__
#endif //__USB_REQUEST_H__

View File

@ -28,61 +28,57 @@
#include "usb_type.h"
#include "usb_queue.h"
const uint8_t* usb_endpoint_descriptor(
const usb_endpoint_t* const endpoint
) {
const uint8_t* usb_endpoint_descriptor(const usb_endpoint_t* const endpoint)
{
const usb_configuration_t* const configuration = endpoint->device->configuration;
if( configuration ) {
if (configuration) {
const uint8_t* descriptor = configuration->descriptor;
while( descriptor[0] != 0 ) {
if( descriptor[1] == USB_DESCRIPTOR_TYPE_ENDPOINT ) {
if( descriptor[2] == endpoint->address ) {
while (descriptor[0] != 0) {
if (descriptor[1] == USB_DESCRIPTOR_TYPE_ENDPOINT) {
if (descriptor[2] == endpoint->address) {
return descriptor;
}
}
descriptor += descriptor[0];
}
}
return 0;
}
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];
}
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);
}
void (*usb_configuration_changed_cb)(usb_device_t* const) = NULL;
void usb_set_configuration_changed_cb(
void (*callback)(usb_device_t* const)
) {
void usb_set_configuration_changed_cb(void (*callback)(usb_device_t* const))
{
usb_configuration_changed_cb = callback;
}
bool usb_set_configuration(
usb_device_t* const device,
const uint_fast8_t configuration_number
) {
const uint_fast8_t configuration_number)
{
const usb_configuration_t* new_configuration = 0;
if( configuration_number != 0 ) {
if (configuration_number != 0) {
// Locate requested configuration.
if( device->configurations ) {
if (device->configurations) {
usb_configuration_t** configurations = *(device->configurations);
uint32_t i = 0;
const usb_speed_t usb_speed_current = usb_speed(device);
while( configurations[i] ) {
if( (configurations[i]->speed == usb_speed_current) &&
(configurations[i]->number == configuration_number) ) {
while (configurations[i]) {
if ((configurations[i]->speed == usb_speed_current) &&
(configurations[i]->number == configuration_number)) {
new_configuration = configurations[i];
break;
}
@ -91,53 +87,58 @@ bool usb_set_configuration(
}
// Requested configuration not found: request error.
if( new_configuration == 0 ) {
if (new_configuration == 0) {
return false;
}
}
if( new_configuration != device->configuration ) {
if (new_configuration != device->configuration) {
// Configuration changed.
device->configuration = new_configuration;
}
if (usb_configuration_changed_cb)
if (usb_configuration_changed_cb) {
usb_configuration_changed_cb(device);
}
return true;
}
static usb_request_status_t usb_send_descriptor(
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;
uint32_t descriptor_length = descriptor_data[0];
if( descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION ) {
if (descriptor_data[1] == USB_DESCRIPTOR_TYPE_CONFIGURATION) {
descriptor_length = (descriptor_data[3] << 8) | descriptor_data[2];
}
// We cast the const away but this shouldn't be a problem as this is a write transfer
usb_transfer_schedule_block(
endpoint->in,
(uint8_t* const) descriptor_data,
(setup_length > descriptor_length) ? descriptor_length : setup_length,
NULL, NULL
);
(setup_length > descriptor_length) ? descriptor_length : setup_length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK;
}
static usb_request_status_t usb_send_descriptor_string(
usb_endpoint_t* const endpoint
) {
static usb_request_status_t usb_send_descriptor_string(usb_endpoint_t* const endpoint)
{
if ((endpoint->setup.value_l == 0xee) &&
(endpoint->device->wcid_string_descriptor != NULL)) { /* MS WCID string */
return usb_send_descriptor(endpoint, endpoint->device->wcid_string_descriptor);
(endpoint->device->wcid_string_descriptor != NULL)) { /* MS WCID string */
return usb_send_descriptor(
endpoint,
endpoint->device->wcid_string_descriptor);
} else {
uint_fast8_t index = endpoint->setup.value_l;
for( uint_fast8_t i=0; endpoint->device->descriptor_strings[i] != 0; i++ ) {
if( i == index ) {
return usb_send_descriptor(endpoint, endpoint->device->descriptor_strings[i]);
for (uint_fast8_t i = 0; endpoint->device->descriptor_strings[i] != 0;
i++) {
if (i == index) {
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(
usb_endpoint_t* const endpoint,
usb_speed_t speed,
const uint8_t config_num
) {
const uint8_t config_num)
{
usb_configuration_t** config = *(endpoint->device->configurations);
unsigned int i = 0;
for( ; *config != NULL; config++ ) {
if( (*config)->speed == speed) {
for (; *config != NULL; config++) {
if ((*config)->speed == speed) {
if (i == config_num) {
return usb_send_descriptor(endpoint, (*config)->descriptor);
return usb_send_descriptor(
endpoint,
(*config)->descriptor);
} else {
i++;
}
@ -164,34 +167,48 @@ static usb_request_status_t usb_send_descriptor_config(
}
static usb_request_status_t usb_standard_request_get_descriptor_setup(
usb_endpoint_t* const endpoint
) {
switch( endpoint->setup.value_h ) {
usb_endpoint_t* const endpoint)
{
switch (endpoint->setup.value_h) {
case USB_DESCRIPTOR_TYPE_DEVICE:
return usb_send_descriptor(endpoint, endpoint->device->descriptor);
case USB_DESCRIPTOR_TYPE_CONFIGURATION:
// TODO: Duplicated code. Refactor.
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
return usb_send_descriptor_config(endpoint, USB_SPEED_HIGH, endpoint->setup.value_l);
if (usb_speed(endpoint->device) == USB_SPEED_HIGH) {
return usb_send_descriptor_config(
endpoint,
USB_SPEED_HIGH,
endpoint->setup.value_l);
} 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:
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:
// TODO: Duplicated code. Refactor.
if( usb_speed(endpoint->device) == USB_SPEED_HIGH ) {
return usb_send_descriptor_config(endpoint, USB_SPEED_FULL, endpoint->setup.value_l);
if (usb_speed(endpoint->device) == USB_SPEED_HIGH) {
return usb_send_descriptor_config(
endpoint,
USB_SPEED_FULL,
endpoint->setup.value_l);
} 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:
return usb_send_descriptor_string(endpoint);
case USB_DESCRIPTOR_TYPE_INTERFACE:
case USB_DESCRIPTOR_TYPE_ENDPOINT:
default:
@ -201,12 +218,12 @@ static usb_request_status_t usb_standard_request_get_descriptor_setup(
static usb_request_status_t usb_standard_request_get_descriptor(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
const usb_transfer_stage_t stage)
{
switch (stage) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_descriptor_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
@ -217,18 +234,22 @@ static usb_request_status_t usb_standard_request_get_descriptor(
}
usb_request_status_t usb_vendor_request_read_wcid(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
if( stage == USB_TRANSFER_STAGE_SETUP ) {
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
if ((endpoint->setup.index == 0x04) &&
(endpoint->device->wcid_feature_descriptor != NULL)) {
usb_send_descriptor(endpoint, endpoint->device->wcid_feature_descriptor);
(endpoint->device->wcid_feature_descriptor != NULL)) {
usb_send_descriptor(
endpoint,
endpoint->device->wcid_feature_descriptor);
return USB_REQUEST_STATUS_OK;
}
if ((endpoint->setup.index == 0x05) &&
(endpoint->device->wcid_extended_properties_descriptor != NULL)) {
usb_send_descriptor(endpoint, endpoint->device->wcid_extended_properties_descriptor);
(endpoint->device->wcid_extended_properties_descriptor != NULL)) {
usb_send_descriptor(
endpoint,
endpoint->device->wcid_extended_properties_descriptor);
return USB_REQUEST_STATUS_OK;
}
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(
usb_endpoint_t* const endpoint
) {
usb_endpoint_t* const endpoint)
{
usb_set_address_deferred(endpoint->device, endpoint->setup.value_l);
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
@ -248,12 +269,12 @@ static usb_request_status_t usb_standard_request_set_address_setup(
static usb_request_status_t usb_standard_request_set_address(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
const usb_transfer_stage_t stage)
{
switch (stage) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_set_address_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
/* NOTE: Not necessary to set address here, as DEVICEADR.USBADRA bit
@ -261,7 +282,7 @@ static usb_request_status_t usb_standard_request_set_address(
* operation on IN ACK.
*/
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
@ -270,10 +291,10 @@ static usb_request_status_t usb_standard_request_set_address(
/*********************************************************************/
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;
if( usb_set_configuration(endpoint->device, usb_configuration) ) {
if (usb_set_configuration(endpoint->device, usb_configuration)) {
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
} else {
@ -283,16 +304,16 @@ static usb_request_status_t usb_standard_request_set_configuration_setup(
static usb_request_status_t usb_standard_request_set_configuration(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
const usb_transfer_stage_t stage)
{
switch (stage) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_set_configuration_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
@ -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(
usb_endpoint_t* const endpoint
) {
if( endpoint->setup.length == 1 ) {
usb_endpoint_t* const endpoint)
{
if (endpoint->setup.length == 1) {
endpoint->buffer[0] = 0;
if( endpoint->device->configuration ) {
if (endpoint->device->configuration) {
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);
return USB_REQUEST_STATUS_OK;
} else {
@ -318,12 +344,12 @@ static usb_request_status_t usb_standard_request_get_configuration_setup(
static usb_request_status_t usb_standard_request_get_configuration(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
const usb_transfer_stage_t stage)
{
switch (stage) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_configuration_setup(endpoint);
case USB_TRANSFER_STAGE_DATA:
case USB_TRANSFER_STAGE_STATUS:
return USB_REQUEST_STATUS_OK;
@ -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(
usb_endpoint_t* const endpoint
) {
if( endpoint->setup.length == 2 ) {
usb_endpoint_t* const endpoint)
{
if (endpoint->setup.length == 2) {
endpoint->buffer[0] = 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);
return USB_REQUEST_STATUS_OK;
} else {
@ -348,12 +379,11 @@ static usb_request_status_t usb_standard_request_get_status_setup(
}
}
static usb_request_status_t usb_standard_request_get_status(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( stage ) {
const usb_transfer_stage_t stage)
{
switch (stage) {
case USB_TRANSFER_STAGE_SETUP:
return usb_standard_request_get_status_setup(endpoint);
@ -369,16 +399,14 @@ static usb_request_status_t usb_standard_request_get_status(
static usb_request_status_t usb_standard_request_clear_feature_setup(
usb_endpoint_t* const endpoint)
{
switch (endpoint->setup.value) {
case USB_FEATURE_SELECTOR_ENDPOINT_HALT:
usb_endpoint_reset_data_toggle(
usb_endpoint_from_address(endpoint->setup.index)
);
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
case USB_FEATURE_SELECTOR_ENDPOINT_HALT:
usb_endpoint_reset_data_toggle(
usb_endpoint_from_address(endpoint->setup.index));
usb_transfer_schedule_ack(endpoint->in);
return USB_REQUEST_STATUS_OK;
default:
return USB_REQUEST_STATUS_STALL;
}
}
@ -403,21 +431,21 @@ static usb_request_status_t usb_standard_request_clear_feature(
usb_request_status_t usb_standard_request(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
switch( endpoint->setup.request ) {
const usb_transfer_stage_t stage)
{
switch (endpoint->setup.request) {
case USB_STANDARD_REQUEST_GET_STATUS:
return usb_standard_request_get_status(endpoint, stage);
case USB_STANDARD_REQUEST_GET_DESCRIPTOR:
return usb_standard_request_get_descriptor(endpoint, stage);
case USB_STANDARD_REQUEST_SET_ADDRESS:
return usb_standard_request_set_address(endpoint, stage);
case USB_STANDARD_REQUEST_SET_CONFIGURATION:
return usb_standard_request_set_configuration(endpoint, stage);
case USB_STANDARD_REQUEST_GET_CONFIGURATION:
return usb_standard_request_get_configuration(endpoint, stage);

View File

@ -25,35 +25,26 @@
#include "usb_type.h"
#include "usb_request.h"
void usb_set_configuration_changed_cb(
void (*callback)(usb_device_t* const)
);
void usb_set_configuration_changed_cb(void (*callback)(usb_device_t* const));
usb_request_status_t usb_vendor_request_read_wcid(
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_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
);
const usb_transfer_stage_t stage);
const uint8_t* usb_endpoint_descriptor(
const usb_endpoint_t* const endpoint
);
const uint8_t* usb_endpoint_descriptor(const usb_endpoint_t* const endpoint);
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(
const uint8_t* const endpoint_descriptor
);
const uint8_t* const endpoint_descriptor);
bool usb_set_configuration(
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

@ -26,32 +26,38 @@
#include <stdbool.h>
// TODO: Move this to some common compiler-tricks location.
#define ATTR_PACKED __attribute__((packed))
#define ATTR_ALIGNED(x) __attribute__ ((aligned(x)))
#define ATTR_SECTION(x) __attribute__ ((section(x)))
#define ATTR_PACKED __attribute__((packed))
#define ATTR_ALIGNED(x) __attribute__((aligned(x)))
#define ATTR_SECTION(x) __attribute__((section(x)))
typedef struct ATTR_PACKED {
uint8_t request_type;
uint8_t request;
union {
struct {
uint8_t value_l;
uint8_t value_h;
};
uint16_t value;
};
union {
struct {
uint8_t index_l;
uint8_t index_h;
};
uint16_t index;
};
union {
struct {
uint8_t length_l;
uint8_t length_h;
};
uint16_t length;
};
} usb_setup_t;
@ -77,23 +83,26 @@ typedef enum {
typedef enum {
USB_SETUP_REQUEST_TYPE_shift = 5,
USB_SETUP_REQUEST_TYPE_mask = 3 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_STANDARD = 0 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_CLASS = 1 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_VENDOR = 2 << 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_mask = 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_DATA_TRANSFER_DIRECTION_mask =
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;
typedef enum {
USB_TRANSFER_DIRECTION_OUT = 0,
USB_TRANSFER_DIRECTION_IN = 1,
} usb_transfer_direction_t;
typedef enum {
USB_DESCRIPTOR_TYPE_DEVICE = 1,
USB_DESCRIPTOR_TYPE_CONFIGURATION = 2,
@ -137,9 +146,10 @@ typedef struct {
} usb_device_t;
typedef struct usb_endpoint_t usb_endpoint_t;
struct usb_endpoint_t {
usb_setup_t setup;
uint8_t buffer[8]; // Buffer for use during IN stage.
uint8_t buffer[8]; // Buffer for use during IN stage.
const uint_fast8_t address;
usb_device_t* const device;
usb_endpoint_t* const in;
@ -148,4 +158,4 @@ struct usb_endpoint_t {
void (*transfer_complete)(usb_endpoint_t* const endpoint);
};
#endif//__USB_TYPE_H__
#endif //__USB_TYPE_H__

View File

@ -45,10 +45,10 @@
#define W25Q80BV_DEVICE_ID 0xAB
#define W25Q80BV_UNIQUE_ID 0x4B
#define W25Q80BV_STATUS_BUSY 0x01
#define W25Q80BV_STATUS_WEL 0x02
#define W25Q80BV_STATUS_BUSY 0x01
#define W25Q80BV_STATUS_WEL 0x02
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
/*
* Set up pins for GPIO and SPI control, configure SSP0 peripheral for SPI.
@ -66,24 +66,21 @@ void w25q80bv_setup(w25q80bv_driver_t* const drv)
do {
device_id = w25q80bv_get_device_id(drv);
} while(device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
} while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
}
uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv)
{
uint8_t data[] = { W25Q80BV_READ_STATUS1, 0xFF };
uint8_t data[] = {W25Q80BV_READ_STATUS1, 0xFF};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
return data[1];
}
/* Release power down / Device ID */
/* Release power down / Device ID */
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
{
uint8_t data[] = {
W25Q80BV_DEVICE_ID,
0xFF, 0xFF, 0xFF, 0xFF
};
uint8_t data[] = {W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
return data[4];
}
@ -92,28 +89,37 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t*
{
uint8_t data[] = {
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));
for(size_t i=0; i<8; i++) {
unique_id->id_8b[i] = data[5+i];
for (size_t i = 0; i < 8; i++) {
unique_id->id_8b[i] = data[5 + i];
}
}
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)
{
w25q80bv_wait_while_busy(drv);
uint8_t data[] = { W25Q80BV_WRITE_ENABLE };
uint8_t data[] = {W25Q80BV_WRITE_ENABLE};
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)
@ -122,26 +128,32 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
do {
device_id = w25q80bv_get_device_id(drv);
} while(device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
} while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
w25q80bv_wait_while_busy(drv);
w25q80bv_write_enable(drv);
uint8_t data[] = { W25Q80BV_CHIP_ERASE };
uint8_t data[] = {W25Q80BV_CHIP_ERASE};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
}
/* 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 */
if (((addr & 0xFF) + len) > drv->page_len)
if (((addr & 0xFF) + len) > drv->page_len) {
return;
}
/* do nothing if we would overflow the flash */
if (addr > (drv->num_bytes - len))
if (addr > (drv->num_bytes - len)) {
return;
}
w25q80bv_wait_while_busy(drv);
w25q80bv_write_enable(drv);
@ -150,37 +162,39 @@ static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t a
W25Q80BV_PAGE_PROGRAM,
(addr & 0xFF0000) >> 16,
(addr & 0xFF00) >> 8,
addr & 0xFF
};
addr & 0xFF};
const spi_transfer_t transfers[] = {
{ header, ARRAY_SIZE(header) },
{ data, len }
};
const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}};
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
}
/* 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;
uint8_t device_id;
do {
device_id = w25q80bv_get_device_id(drv);
} while(device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
} while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES);
/* do nothing if we would overflow the flash */
if ((len > drv->num_bytes) || (addr > drv->num_bytes)
|| ((addr + len) > drv->num_bytes))
if ((len > drv->num_bytes) || (addr > drv->num_bytes) ||
((addr + len) > drv->num_bytes)) {
return;
}
/* handle start not at page boundary */
first_block_len = drv->page_len - (addr % drv->page_len);
if (len < first_block_len)
if (len < first_block_len) {
first_block_len = len;
}
if (first_block_len) {
w25q80bv_page_program(drv, addr, first_block_len, data);
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 */
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 */
if ((len > drv->num_bytes) || (addr > drv->num_bytes)
|| ((addr + len) > drv->num_bytes))
if ((len > drv->num_bytes) || (addr > drv->num_bytes) ||
((addr + len) > drv->num_bytes)) {
return;
}
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 & 0xFF00) >> 8,
addr & 0xFF,
0x00
};
0x00};
const spi_transfer_t transfers[] = {
{ header, ARRAY_SIZE(header) },
{ data, len }
};
const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}};
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
}
@ -232,16 +247,16 @@ void w25q80bv_clear_status(w25q80bv_driver_t* const drv)
{
w25q80bv_wait_while_busy(drv);
w25q80bv_write_enable(drv);
uint8_t data[] = { W25Q80BV_WRITE_STATUS, 0x00, 0x00 };
uint8_t data[] = {W25Q80BV_WRITE_STATUS, 0x00, 0x00};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
}
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data)
{
uint8_t cmd[] = { W25Q80BV_READ_STATUS1, 0xFF };
uint8_t cmd[] = {W25Q80BV_READ_STATUS1, 0xFF};
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[0] = cmd[1];
cmd[0] =W25Q80BV_READ_STATUS2;
cmd[0] = W25Q80BV_READ_STATUS2;
cmd[1] = 0xFF;
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[1] = cmd[1];

View File

@ -27,16 +27,15 @@
#include <stdint.h>
#include <stddef.h>
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
#define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
#define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */
#include "spi_bus.h"
#include "gpio.h"
typedef union
{
typedef union {
uint64_t id_64b;
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 */
} w25q80bv_unique_id_t;
struct w25q80bv_driver_t;
@ -55,10 +54,18 @@ struct w25q80bv_driver_t {
void w25q80bv_setup(w25q80bv_driver_t* const drv);
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data);
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);
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);
#endif//__W25Q80BV_H__
#endif //__W25Q80BV_H__

View File

@ -28,21 +28,29 @@
* automatically?
*/
void w25q80bv_target_init(w25q80bv_driver_t* const drv) {
(void)drv;
void w25q80bv_target_init(w25q80bv_driver_t* const drv)
{
(void) drv;
/* 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]
scu_pinmux(P3_5, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_5 SPIFI SPIFI_SIO2 IO2 => GPIO1[15]
scu_pinmux(P3_6, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0)); // P3_6 SPIFI SPIFI_CIPO IO1 => GPIO0[6]
scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_7 SPIFI SPIFI_COPI IO0 => GPIO5[10]
scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); // P3_8 SPIFI SPIFI_CS => GPIO5[11]
// P3_3 SPIFI_SCK => SSP0_SCK
scu_pinmux(P3_3, (SCU_SSP_IO | SCU_CONF_FUNCTION2));
// P3_4 SPIFI SPIFI_SIO3 IO3 => GPIO1[14]
scu_pinmux(P3_4, (SCU_GPIO_FAST | SCU_CONF_FUNCTION0));
// 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 */
scu_pinmux(SCU_SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP0_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2));
scu_pinmux(SCU_SSP0_SCK, (SCU_SSP_IO | SCU_CONF_FUNCTION2));
/* configure GPIO pins */
scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST);

View File

@ -26,4 +26,4 @@
void w25q80bv_target_init(w25q80bv_driver_t* const drv);
#endif/*__W25Q80BV_TARGET_H__*/
#endif /*__W25Q80BV_TARGET_H__*/

View File

@ -52,7 +52,7 @@
#include "usb_api_m0_state.h"
#include "cpld_xc2c.h"
#include "portapack.h"
#include "hackrf_ui.h"
extern uint32_t __m0_start__;
@ -95,7 +95,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
NULL,
#endif
usb_vendor_request_set_freq_explicit,
usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ
usb_vendor_request_read_wcid, // USB_WCID_VENDOR_REQ
usb_vendor_request_init_sweep,
usb_vendor_request_operacake_get_boards,
usb_vendor_request_operacake_set_ports,
@ -125,17 +125,18 @@ static const uint32_t vendor_request_handler_count =
usb_request_status_t usb_vendor_request(
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;
if( endpoint->setup.request < vendor_request_handler_count ) {
usb_request_handler_fn handler = vendor_request_handler[endpoint->setup.request];
if( handler ) {
if (endpoint->setup.request < vendor_request_handler_count) {
usb_request_handler_fn handler =
vendor_request_handler[endpoint->setup.request];
if (handler) {
status = handler(endpoint, stage);
}
}
return status;
}
@ -146,12 +147,11 @@ const usb_request_handlers_t usb_request_handlers = {
.reserved = 0,
};
void usb_configuration_changed(
usb_device_t* const device
) {
void usb_configuration_changed(usb_device_t* const device)
{
/* Reset transceiver to idle state until other commands are received */
request_transceiver_mode(TRANSCEIVER_MODE_OFF);
if( device->configuration->number == 1 ) {
if (device->configuration->number == 1) {
// transceiver configuration
led_on(LED1);
} else {
@ -165,19 +165,24 @@ void usb_configuration_changed(
void usb_set_descriptor_by_serial_number(void)
{
iap_cmd_res_t iap_cmd_res;
/* Read IAP Serial Number Identification */
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO;
iap_cmd_call(&iap_cmd_res);
if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) {
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;
/* 32 characters of serial number, convert to UTF-16LE */
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 char c = (nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble);
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 char c =
(nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble);
usb_descriptor_string_serial_number[2 + i * 2] = c;
usb_descriptor_string_serial_number[3 + i * 2] = 0x00;
}
@ -187,28 +192,34 @@ 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_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);
return success;
}
static void m0_rom_to_ram() {
uint32_t *dest = &__ram_m0_start__;
static void m0_rom_to_ram()
{
uint32_t* dest = &__ram_m0_start__;
// Calculate the base address of ROM
uint32_t base = (uint32_t)(&_etext_rom - (&_etext_ram - &_text_ram));
uint32_t base = (uint32_t) (&_etext_rom - (&_etext_ram - &_text_ram));
// M0 image location, relative to the start of ROM
uint32_t src = (uint32_t)&__m0_start__;
uint32_t src = (uint32_t) &__m0_start__;
uint32_t len = (uint32_t)&__m0_end__ - (uint32_t)src;
memcpy(dest, (uint32_t*)(base + src), len);
uint32_t len = (uint32_t) &__m0_end__ - (uint32_t) src;
memcpy(dest, (uint32_t*) (base + src), len);
}
int main(void) {
int main(void)
{
// Copy M0 image from ROM before SPIFI is disabled
m0_rom_to_ram();
@ -223,9 +234,9 @@ int main(void) {
cpu_clock_init();
/* Wake the M0 */
ipc_start_m0((uint32_t)&__ram_m0_start__);
ipc_start_m0((uint32_t) &__ram_m0_start__);
if( !cpld_jtag_sram_load(&jtag_cpld) ) {
if (!cpld_jtag_sram_load(&jtag_cpld)) {
halt_and_flash(6000000);
}
@ -239,9 +250,9 @@ int main(void) {
usb_set_configuration_changed_cb(usb_configuration_changed);
usb_peripheral_reset();
usb_device_init(0, &usb_device);
usb_queue_init(&usb_endpoint_control_out_queue);
usb_queue_init(&usb_endpoint_control_in_queue);
usb_queue_init(&usb_endpoint_bulk_out_queue);
@ -249,24 +260,24 @@ int main(void) {
usb_endpoint_init(&usb_endpoint_control_out);
usb_endpoint_init(&usb_endpoint_control_in);
nvic_set_priority(NVIC_USB0_IRQ, 255);
hackrf_ui()->init();
usb_run(&usb_device);
rf_path_init(&rf_path);
bool operacake_allow_gpio;
if( hackrf_ui()->operacake_gpio_compatible() ) {
if (hackrf_ui()->operacake_gpio_compatible()) {
operacake_allow_gpio = true;
} else {
operacake_allow_gpio = false;
}
operacake_init(operacake_allow_gpio);
while(true) {
while (true) {
transceiver_request_t request;
// Briefly disable USB interrupt so that we can

View File

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

View File

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

View File

@ -39,8 +39,8 @@ volatile bool cpld_wait = false;
static void cpld_buffer_refilled(void* user_data, unsigned int length)
{
(void)user_data;
(void)length;
(void) user_data;
(void) length;
cpld_wait = false;
}
@ -52,11 +52,10 @@ static void refill_cpld_buffer(void)
cpld_xsvf_buffer,
sizeof(cpld_xsvf_buffer),
cpld_buffer_refilled,
NULL
);
NULL);
// Wait until transfer finishes
while (cpld_wait);
while (cpld_wait) {}
}
void cpld_update(void)
@ -68,40 +67,47 @@ void cpld_update(void)
refill_cpld_buffer();
error = cpld_jtag_program(&jtag_cpld, sizeof(cpld_xsvf_buffer),
cpld_xsvf_buffer,
refill_cpld_buffer);
if(error == 0)
{
error = cpld_jtag_program(
&jtag_cpld,
sizeof(cpld_xsvf_buffer),
cpld_xsvf_buffer,
refill_cpld_buffer);
if (error == 0) {
halt_and_flash(6000000);
}else
{
} else {
/* LED3 (Red) steady on error */
led_on(LED3);
while (1);
while (1) {}
}
}
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;
uint8_t length;
if (stage == USB_TRANSFER_STAGE_SETUP)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
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);
if(!checksum_success) {
if (!checksum_success) {
return USB_REQUEST_STATUS_STALL;
}
length = (uint8_t)sizeof(cpld_crc);
length = (uint8_t) sizeof(cpld_crc);
memcpy(endpoint->buffer, &cpld_crc, length);
usb_transfer_schedule_block(endpoint->in, endpoint->buffer, length,
NULL, NULL);
usb_transfer_schedule_block(
endpoint->in,
endpoint->buffer,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
}
return USB_REQUEST_STATUS_OK;

View File

@ -31,6 +31,7 @@
void cpld_update(void);
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__ */

View File

@ -38,20 +38,20 @@ void m0_set_mode(enum m0_mode mode)
SGPIO_SET_STATUS_1 = (1 << SGPIO_SLICE_A);
// 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_endpoint_t* const endpoint,
const usb_transfer_stage_t stage
) {
if( stage == USB_TRANSFER_STAGE_SETUP )
{
const usb_transfer_stage_t stage)
{
if (stage == USB_TRANSFER_STAGE_SETUP) {
usb_transfer_schedule_block(
endpoint->in,
(void*) &m0_state,
sizeof(m0_state),
NULL, NULL);
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK;
} else {

View File

@ -63,6 +63,7 @@ extern volatile struct m0_state m0_state;
void m0_set_mode(enum m0_mode mode);
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>
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) {
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_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;
address = endpoint->setup.value & 0xFF;
@ -53,26 +55,31 @@ usb_request_status_t usb_vendor_request_operacake_set_ports(
}
static unsigned char data[MAX_OPERACAKE_RANGES * 5];
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;
uint8_t port;
if (stage == USB_TRANSFER_STAGE_SETUP) {
num_ranges = endpoint->setup.length / 5;
if((num_ranges == 0) || (num_ranges > MAX_OPERACAKE_RANGES)) {
num_ranges = endpoint->setup.length / 5;
if ((num_ranges == 0) || (num_ranges > MAX_OPERACAKE_RANGES)) {
return USB_REQUEST_STATUS_STALL;
}
operacake_clear_ranges();
usb_transfer_schedule_block(endpoint->out, &data,
endpoint->setup.length, NULL, NULL);
usb_transfer_schedule_block(
endpoint->out,
&data,
endpoint->setup.length,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
for(i=0; i<endpoint->setup.length; i+=5) {
freq_min = data[i] << 8 | data[i+1];
freq_max = data[i+2] << 8 | data[i+3];
port = data[i+4];
for (i = 0; i < endpoint->setup.length; i += 5) {
freq_min = data[i] << 8 | data[i + 1];
freq_max = data[i + 2] << 8 | data[i + 3];
port = data[i + 4];
operacake_add_range(freq_min, freq_max, port);
}
usb_transfer_schedule_ack(endpoint->in);
@ -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_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;
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);
endpoint->buffer[0] = test_result & 0xff;
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);
}
return USB_REQUEST_STATUS_OK;
}
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;
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_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{
uint8_t address;
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];
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;
uint32_t dwell;
@ -131,17 +148,22 @@ usb_request_status_t usb_vendor_request_operacake_set_dwell_times(
if (stage == USB_TRANSFER_STAGE_SETUP) {
count = endpoint->setup.length / 5;
if((count == 0) || (count > SCT_EVENT_COUNT)) {
if ((count == 0) || (count > SCT_EVENT_COUNT)) {
return USB_REQUEST_STATUS_STALL;
}
usb_transfer_schedule_block(endpoint->out, &data,
endpoint->setup.length, NULL, NULL);
usb_transfer_schedule_block(
endpoint->out,
&data,
endpoint->setup.length,
NULL,
NULL);
} else if (stage == USB_TRANSFER_STAGE_DATA) {
count = endpoint->setup.length / 5;
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);
port = data[(i*5)+4];
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);
port = data[(i * 5) + 4];
dwell_times[i].dwell = dwell;
dwell_times[i].port = port;
}

View File

@ -25,25 +25,32 @@
#include <usb_type.h>
#include <usb_request.h>
usb_request_status_t usb_vendor_request_operacake_get_boards(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);
usb_request_status_t usb_vendor_request_operacake_get_boards(
usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage);
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_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_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_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_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_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__ */

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