Reformat all code to new clang-format standard.

This commit is contained in:
Martin Ling
2022-07-06 12:50:08 +01:00
parent 7d6a524795
commit c3fdf402d7
122 changed files with 6113 additions and 4930 deletions

View File

@ -21,25 +21,40 @@
#include "bitband.h" #include "bitband.h"
volatile uint32_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number) { volatile uint32_t* peripheral_bitband_address(
const uint32_t bit_band_base = 0x42000000; volatile void* const address,
const uint32_t byte_offset = (uint32_t)address - 0x40000000; const uint_fast8_t bit_number)
const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4); {
const uint32_t bit_word_address = bit_band_base + bit_word_offset; const uint32_t bit_band_base = 0x42000000;
return (volatile uint32_t*)bit_word_address; 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) { void peripheral_bitband_set(
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); volatile void* const peripheral_address,
*bitband_address = 1; 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) { void peripheral_bitband_clear(
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); volatile void* const peripheral_address,
*bitband_address = 0; 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) { uint32_t peripheral_bitband_get(
volatile uint32_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); volatile void* const peripheral_address,
return *bitband_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> #include <stdint.h>
volatile uint32_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number); volatile uint32_t* peripheral_bitband_address(
void peripheral_bitband_set(volatile void* const peripheral_address, const uint_fast8_t bit_number); volatile void* const address,
void peripheral_bitband_clear(volatile void* const peripheral_address, const uint_fast8_t bit_number); const uint_fast8_t bit_number);
uint32_t peripheral_bitband_get(volatile void* const peripheral_address, const uint_fast8_t bit_number); void peripheral_bitband_set(
volatile void* const peripheral_address,
const uint_fast8_t bit_number);
void peripheral_bitband_clear(
volatile void* const peripheral_address,
const uint_fast8_t bit_number);
uint32_t peripheral_bitband_get(
volatile void* const peripheral_address,
const uint_fast8_t bit_number);
#endif//__BITBAND_H__ #endif //__BITBAND_H__

View File

@ -29,7 +29,8 @@ static refill_buffer_cb refill_buffer;
static uint32_t xsvf_buffer_len, xsvf_pos; static uint32_t xsvf_buffer_len, xsvf_pos;
static unsigned char* xsvf_buffer; static unsigned char* xsvf_buffer;
void cpld_jtag_take(jtag_t* const jtag) { void cpld_jtag_take(jtag_t* const jtag)
{
const jtag_gpio_t* const gpio = jtag->gpio; const jtag_gpio_t* const gpio = jtag->gpio;
/* Set initial GPIO state to the voltages of the internal or external pull-ups/downs, /* Set initial GPIO state to the voltages of the internal or external pull-ups/downs,
@ -53,7 +54,8 @@ void cpld_jtag_take(jtag_t* const jtag) {
gpio_input(gpio->gpio_tdo); gpio_input(gpio->gpio_tdo);
} }
void cpld_jtag_release(jtag_t* const jtag) { void cpld_jtag_release(jtag_t* const jtag)
{
const jtag_gpio_t* const gpio = jtag->gpio; const jtag_gpio_t* const gpio = jtag->gpio;
/* Make all pins inputs when JTAG interface not active. /* Make all pins inputs when JTAG interface not active.
@ -72,30 +74,31 @@ void cpld_jtag_release(jtag_t* const jtag) {
/* return 0 if success else return error code see xsvfExecute() */ /* return 0 if success else return error code see xsvfExecute() */
int cpld_jtag_program( int cpld_jtag_program(
jtag_t* const jtag, jtag_t* const jtag,
const uint32_t buffer_length, const uint32_t buffer_length,
unsigned char* const buffer, unsigned char* const buffer,
refill_buffer_cb refill refill_buffer_cb refill)
) { {
int error; int error;
cpld_jtag_take(jtag); cpld_jtag_take(jtag);
xsvf_buffer = buffer; xsvf_buffer = buffer;
xsvf_buffer_len = buffer_length; xsvf_buffer_len = buffer_length;
refill_buffer = refill; refill_buffer = refill;
error = xsvfExecute(jtag->gpio); error = xsvfExecute(jtag->gpio);
cpld_jtag_release(jtag); cpld_jtag_release(jtag);
return error; return error;
} }
/* this gets called by the XAPP058 code */ /* this gets called by the XAPP058 code */
unsigned char cpld_jtag_get_next_byte(void) { unsigned char cpld_jtag_get_next_byte(void)
if (xsvf_pos == xsvf_buffer_len) { {
refill_buffer(); if (xsvf_pos == xsvf_buffer_len) {
xsvf_pos = 0; refill_buffer();
} xsvf_pos = 0;
}
unsigned char byte = xsvf_buffer[xsvf_pos]; unsigned char byte = xsvf_buffer[xsvf_pos];
xsvf_pos++; xsvf_pos++;
return byte; 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 * contents of the buffer has been streamed to the CPLD the given
* refill_buffer callback will be called. */ * refill_buffer callback will be called. */
int cpld_jtag_program( int cpld_jtag_program(
jtag_t* const jtag, jtag_t* const jtag,
const uint32_t buffer_length, const uint32_t buffer_length,
unsigned char* const buffer, unsigned char* const buffer,
refill_buffer_cb refill refill_buffer_cb refill);
);
unsigned char cpld_jtag_get_next_byte(void); unsigned char cpld_jtag_get_next_byte(void);
#endif//__CPLD_JTAG_H__ #endif //__CPLD_JTAG_H__

View File

@ -53,9 +53,14 @@ typedef enum {
CPLD_XC2C_IR_STCTEST = 0b00010110, CPLD_XC2C_IR_STCTEST = 0b00010110,
CPLD_XC2C_IR_ISC_NOOP = 0b11100000, CPLD_XC2C_IR_ISC_NOOP = 0b11100000,
} cpld_xc2c_ir_t; } cpld_xc2c_ir_t;
// clang-format on // clang-format on
static bool cpld_xc2c_jtag_clock(const jtag_t* const jtag, const uint32_t tms, const uint32_t tdi) { static bool cpld_xc2c_jtag_clock(
const jtag_t* const jtag,
const uint32_t tms,
const uint32_t tdi)
{
// 8 ns TMS/TDI to TCK setup // 8 ns TMS/TDI to TCK setup
gpio_write(jtag->gpio->gpio_tdi, tdi); gpio_write(jtag->gpio->gpio_tdi, tdi);
gpio_write(jtag->gpio->gpio_tms, tms); gpio_write(jtag->gpio->gpio_tms, tms);
@ -78,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"); __asm__("nop");
__asm__("nop"); __asm__("nop");
gpio_set(jtag->gpio->gpio_tck); gpio_set(jtag->gpio->gpio_tck);
// 15 ns TCK to TMS/TDI hold time // 15 ns TCK to TMS/TDI hold time
@ -90,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); return gpio_read(jtag->gpio->gpio_tdo);
} }
static void cpld_xc2c_jtag_shift_ptr_tms(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t start, const size_t end, const bool tms) { static void cpld_xc2c_jtag_shift_ptr_tms(
for(size_t i=start; i<end; i++) { 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 byte_n = i >> 3;
const size_t bit_n = i & 7; const size_t bit_n = i & 7;
const uint32_t mask = (1U << bit_n); const uint32_t mask = (1U << bit_n);
const uint32_t tdo = cpld_xc2c_jtag_clock(jtag, tms, tdi_tdo[byte_n] & mask) ? 1 : 0; const uint32_t tdo =
cpld_xc2c_jtag_clock(jtag, tms, tdi_tdo[byte_n] & mask) ? 1 : 0;
tdi_tdo[byte_n] &= ~mask; tdi_tdo[byte_n] &= ~mask;
tdi_tdo[byte_n] |= (tdo << bit_n); tdi_tdo[byte_n] |= (tdo << bit_n);
} }
} }
static void cpld_xc2c_jtag_shift_ptr(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t count) { static void cpld_xc2c_jtag_shift_ptr(
if( count > 0 ) { 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, 0, count - 1, false);
cpld_xc2c_jtag_shift_ptr_tms(jtag, tdi_tdo, count - 1, count, true); cpld_xc2c_jtag_shift_ptr_tms(jtag, tdi_tdo, count - 1, count, true);
} }
} }
static uint32_t cpld_xc2c_jtag_shift_u32(const jtag_t* const jtag, const uint32_t tms, const uint32_t tdi, const size_t count) { static uint32_t cpld_xc2c_jtag_shift_u32(
const jtag_t* const jtag,
const uint32_t tms,
const uint32_t tdi,
const size_t count)
{
uint32_t tdo = 0; uint32_t tdo = 0;
for(size_t i=0; i<count; i++) { for (size_t i = 0; i < count; i++) {
const uint32_t mask = (1U << i); const uint32_t mask = (1U << i);
tdo |= cpld_xc2c_jtag_clock(jtag, tms & mask, tdi & mask) << i; tdo |= cpld_xc2c_jtag_clock(jtag, tms & mask, tdi & mask) << i;
} }
@ -121,24 +142,31 @@ static uint32_t cpld_xc2c_jtag_shift_u32(const jtag_t* const jtag, const uint32_
return tdo; return tdo;
} }
static void cpld_xc2c_jtag_clocks(const jtag_t* const jtag, const size_t count) { static void cpld_xc2c_jtag_clocks(const jtag_t* const jtag, const size_t count)
for(size_t i=0; i<count; i++) { {
for (size_t i = 0; i < count; i++) {
cpld_xc2c_jtag_clock(jtag, 0, 0); cpld_xc2c_jtag_clock(jtag, 0, 0);
} }
} }
static void cpld_xc2c_jtag_pause(const jtag_t* const jtag, const size_t count) { static void cpld_xc2c_jtag_pause(const jtag_t* const jtag, const size_t count)
for(size_t i=0; i<count; i++) { {
for (size_t i = 0; i < count; i++) {
cpld_xc2c_jtag_clock(jtag, (i == (count - 1)), 0); cpld_xc2c_jtag_clock(jtag, (i == (count - 1)), 0);
} }
} }
static void cpld_xc2c_jtag_shift_dr_ir(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t bit_count, const size_t pause_count) { static void cpld_xc2c_jtag_shift_dr_ir(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t bit_count,
const size_t pause_count)
{
/* Run-Test/Idle or Select-DR-Scan -> Shift-DR or Shift-IR */ /* Run-Test/Idle or Select-DR-Scan -> Shift-DR or Shift-IR */
cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3); cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3);
/* Shift-[DI]R -> Exit1-[DI]R */ /* Shift-[DI]R -> Exit1-[DI]R */
cpld_xc2c_jtag_shift_ptr(jtag, tdi_tdo, bit_count); cpld_xc2c_jtag_shift_ptr(jtag, tdi_tdo, bit_count);
if( pause_count ) { if (pause_count) {
/* Exit1-[DI]R -> Pause-[DI]R */ /* Exit1-[DI]R -> Pause-[DI]R */
cpld_xc2c_jtag_shift_u32(jtag, 0b0, 0, 1); cpld_xc2c_jtag_shift_u32(jtag, 0b0, 0, 1);
/* Pause-[DI]R -> Exit2-[DI]R */ /* Pause-[DI]R -> Exit2-[DI]R */
@ -148,11 +176,20 @@ static void cpld_xc2c_jtag_shift_dr_ir(const jtag_t* const jtag, uint8_t* const
cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0, 2); cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0, 2);
} }
static void cpld_xc2c_jtag_shift_dr(const jtag_t* const jtag, uint8_t* const tdi_tdo, const size_t bit_count, const size_t pause_count) { static void cpld_xc2c_jtag_shift_dr(
const jtag_t* const jtag,
uint8_t* const tdi_tdo,
const size_t bit_count,
const size_t pause_count)
{
cpld_xc2c_jtag_shift_dr_ir(jtag, tdi_tdo, bit_count, pause_count); cpld_xc2c_jtag_shift_dr_ir(jtag, tdi_tdo, bit_count, pause_count);
} }
static uint8_t cpld_xc2c_jtag_shift_ir_pause(const jtag_t* const jtag, const cpld_xc2c_ir_t ir, const size_t pause_count) { static uint8_t cpld_xc2c_jtag_shift_ir_pause(
const jtag_t* const jtag,
const cpld_xc2c_ir_t ir,
const size_t pause_count)
{
/* Run-Test/Idle -> Select-DR-Scan */ /* Run-Test/Idle -> Select-DR-Scan */
cpld_xc2c_jtag_shift_u32(jtag, 0b1, 0b0, 1); cpld_xc2c_jtag_shift_u32(jtag, 0b1, 0b0, 1);
uint8_t value = ir; uint8_t value = ir;
@ -160,17 +197,20 @@ static uint8_t cpld_xc2c_jtag_shift_ir_pause(const jtag_t* const jtag, const cpl
return value; return value;
} }
static uint8_t cpld_xc2c_jtag_shift_ir(const jtag_t* const jtag, const cpld_xc2c_ir_t ir) { static uint8_t cpld_xc2c_jtag_shift_ir(const jtag_t* const jtag, const cpld_xc2c_ir_t ir)
{
return cpld_xc2c_jtag_shift_ir_pause(jtag, ir, 0); return cpld_xc2c_jtag_shift_ir_pause(jtag, ir, 0);
} }
static void cpld_xc2c_jtag_reset(const jtag_t* const jtag) { static void cpld_xc2c_jtag_reset(const jtag_t* const jtag)
{
/* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram. /* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram.
*/ */
cpld_xc2c_jtag_shift_u32(jtag, 0b11111, 0, 5); cpld_xc2c_jtag_shift_u32(jtag, 0b11111, 0, 5);
} }
static void cpld_xc2c_jtag_reset_and_idle(const jtag_t* const jtag) { static void cpld_xc2c_jtag_reset_and_idle(const jtag_t* const jtag)
{
/* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram. /* Five TMS=1 to reach Test-Logic-Reset from any point in the TAP state diagram.
* One TMS=0 to move from Test-Logic-Reset to Run-Test-Idle. * One TMS=0 to move from Test-Logic-Reset to Run-Test-Idle.
*/ */
@ -178,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); cpld_xc2c_jtag_shift_u32(jtag, 0, 0, 1);
} }
static uint32_t cpld_xc2c_jtag_idcode(const jtag_t* const jtag) { static uint32_t cpld_xc2c_jtag_idcode(const jtag_t* const jtag)
{
/* Enter and end at Run-Test-Idle state. */ /* Enter and end at Run-Test-Idle state. */
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_IDCODE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_IDCODE);
uint32_t result = 0; uint32_t result = 0;
cpld_xc2c_jtag_shift_dr(jtag, (uint8_t*)&result, 32, 0); cpld_xc2c_jtag_shift_dr(jtag, (uint8_t*) &result, 32, 0);
return result; return result;
} }
static bool cpld_xc2c64a_jtag_idcode_ok(const jtag_t* const jtag) { static bool cpld_xc2c64a_jtag_idcode_ok(const jtag_t* const jtag)
{
return ((cpld_xc2c_jtag_idcode(jtag) ^ 0xf6e5f093) & 0x0fff8fff) == 0; return ((cpld_xc2c_jtag_idcode(jtag) ^ 0xf6e5f093) & 0x0fff8fff) == 0;
} }
static void cpld_xc2c_jtag_conld(const jtag_t* const jtag) { static void cpld_xc2c_jtag_conld(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE);
cpld_xc2c_jtag_clocks(jtag, 100); cpld_xc2c_jtag_clocks(jtag, 100);
} }
static void cpld_xc2c_jtag_enable(const jtag_t* const jtag) { static void cpld_xc2c_jtag_enable(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_ENABLE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_ENABLE);
cpld_xc2c_jtag_clocks(jtag, 800); cpld_xc2c_jtag_clocks(jtag, 800);
} }
static void cpld_xc2c_jtag_disable(const jtag_t* const jtag) { static void cpld_xc2c_jtag_disable(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_DISABLE);
cpld_xc2c_jtag_clocks(jtag, 100); cpld_xc2c_jtag_clocks(jtag, 100);
} }
static void cpld_xc2c_jtag_sram_write(const jtag_t* const jtag) { static void cpld_xc2c_jtag_sram_write(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_WRITE); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_WRITE);
} }
static void cpld_xc2c_jtag_sram_read(const jtag_t* const jtag) { static void cpld_xc2c_jtag_sram_read(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_SRAM_READ); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_SRAM_READ);
} }
static uint32_t cpld_xc2c_jtag_bypass(const jtag_t* const jtag, const bool shift_dr) { static uint32_t cpld_xc2c_jtag_bypass(const jtag_t* const jtag, const bool shift_dr)
{
const uint8_t result = cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_BYPASS); const uint8_t result = cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_BYPASS);
if( shift_dr ) { if (shift_dr) {
uint8_t dr = 0; uint8_t dr = 0;
cpld_xc2c_jtag_shift_dr(jtag, &dr, 1, 0); cpld_xc2c_jtag_shift_dr(jtag, &dr, 1, 0);
} }
return result; return result;
} }
static bool cpld_xc2c_jtag_read_write_protect(const jtag_t* const jtag) { static bool cpld_xc2c_jtag_read_write_protect(const jtag_t* const jtag)
{
/* Enter and end at Run-Test-Idle state. */ /* Enter and end at Run-Test-Idle state. */
return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x01) & 0x03) == 0; return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x01) & 0x03) == 0;
} }
static bool cpld_xc2c_jtag_is_done(const jtag_t* const jtag) { static bool cpld_xc2c_jtag_is_done(const jtag_t* const jtag)
{
return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x05) & 0x07) == 0; return ((cpld_xc2c_jtag_bypass(jtag, false) ^ 0x05) & 0x07) == 0;
} }
static void cpld_xc2c_jtag_init_special(const jtag_t* const jtag) { static void cpld_xc2c_jtag_init_special(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_INIT); cpld_xc2c_jtag_shift_ir(jtag, CPLD_XC2C_IR_ISC_INIT);
cpld_xc2c_jtag_clocks(jtag, 20); cpld_xc2c_jtag_clocks(jtag, 20);
/* Run-Test/Idle -> Shift-IR */ /* Run-Test/Idle -> Shift-IR */
@ -245,11 +296,16 @@ static void cpld_xc2c_jtag_init_special(const jtag_t* const jtag) {
cpld_xc2c_jtag_clocks(jtag, 800); cpld_xc2c_jtag_clocks(jtag, 800);
} }
static void cpld_xc2c_jtag_read(const jtag_t* const jtag) { static void cpld_xc2c_jtag_read(const jtag_t* const jtag)
{
cpld_xc2c_jtag_shift_ir_pause(jtag, CPLD_XC2C_IR_ISC_READ, 1); cpld_xc2c_jtag_shift_ir_pause(jtag, CPLD_XC2C_IR_ISC_READ, 1);
} }
static void cpld_xc2c64a_jtag_read_row(const jtag_t* const jtag, uint8_t address, uint8_t* const dr) { static void cpld_xc2c64a_jtag_read_row(
const jtag_t* const jtag,
uint8_t address,
uint8_t* const dr)
{
cpld_xc2c_jtag_shift_dr(jtag, &address, 7, 20); cpld_xc2c_jtag_shift_dr(jtag, &address, 7, 20);
cpld_xc2c_jtag_clocks(jtag, 100); cpld_xc2c_jtag_clocks(jtag, 100);
@ -264,13 +320,14 @@ static void cpld_xc2c64a_jtag_read_row(const jtag_t* const jtag, uint8_t address
bool cpld_xc2c64a_jtag_checksum( bool cpld_xc2c64a_jtag_checksum(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_verify_t* const verify, const cpld_xc2c64a_verify_t* const verify,
uint32_t* const crc_value uint32_t* const crc_value)
) { {
cpld_xc2c_jtag_reset_and_idle(jtag); cpld_xc2c_jtag_reset_and_idle(jtag);
if( cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_read_write_protect(jtag) && if (cpld_xc2c64a_jtag_idcode_ok(jtag) &&
cpld_xc2c64a_jtag_idcode_ok(jtag) && cpld_xc2c_jtag_read_write_protect(jtag) ) { cpld_xc2c_jtag_read_write_protect(jtag) &&
cpld_xc2c64a_jtag_idcode_ok(jtag) &&
cpld_xc2c_jtag_read_write_protect(jtag)) {
cpld_xc2c_jtag_bypass(jtag, false); cpld_xc2c_jtag_bypass(jtag, false);
cpld_xc2c_jtag_enable(jtag); cpld_xc2c_jtag_enable(jtag);
@ -283,12 +340,12 @@ bool cpld_xc2c64a_jtag_checksum(
crc32_init(&crc); crc32_init(&crc);
uint8_t dr[CPLD_XC2C64A_BYTES_IN_ROW]; 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]; const size_t address = cpld_hackrf_row_addresses.address[row];
cpld_xc2c64a_jtag_read_row(jtag, address, dr); cpld_xc2c64a_jtag_read_row(jtag, address, dr);
const size_t mask_index = verify->mask_index[row]; 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]; dr[i] &= verify->mask[mask_index].value[i];
} }
@ -305,7 +362,7 @@ bool cpld_xc2c64a_jtag_checksum(
cpld_xc2c_jtag_init_special(jtag); cpld_xc2c_jtag_init_special(jtag);
cpld_xc2c_jtag_conld(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_conld(jtag);
cpld_xc2c_jtag_bypass(jtag, false); cpld_xc2c_jtag_bypass(jtag, false);
cpld_xc2c_jtag_bypass(jtag, true); cpld_xc2c_jtag_bypass(jtag, true);
@ -319,7 +376,11 @@ bool cpld_xc2c64a_jtag_checksum(
return false; return false;
} }
static void cpld_xc2c64a_jtag_sram_write_row(const jtag_t* const jtag, uint8_t address, const uint8_t* const data) { static void cpld_xc2c64a_jtag_sram_write_row(
const jtag_t* const jtag,
uint8_t address,
const uint8_t* const data)
{
uint8_t write[CPLD_XC2C64A_BYTES_IN_ROW]; uint8_t write[CPLD_XC2C64A_BYTES_IN_ROW];
memcpy(&write[0], data, sizeof(write)); memcpy(&write[0], data, sizeof(write));
@ -336,7 +397,11 @@ static void cpld_xc2c64a_jtag_sram_write_row(const jtag_t* const jtag, uint8_t a
cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0b00, 2); cpld_xc2c_jtag_shift_u32(jtag, 0b01, 0b00, 2);
} }
static void cpld_xc2c64a_jtag_sram_read_row(const jtag_t* const jtag, uint8_t* const data, const uint8_t next_address) { static void cpld_xc2c64a_jtag_sram_read_row(
const jtag_t* const jtag,
uint8_t* const data,
const uint8_t next_address)
{
/* Run-Test/Idle -> Shift-DR */ /* Run-Test/Idle -> Shift-DR */
cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3); cpld_xc2c_jtag_shift_u32(jtag, 0b001, 0b000, 3);
@ -353,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); cpld_xc2c_jtag_shift_u32(jtag, 0b0110, 0b0000, 4);
} }
static bool cpld_xc2c64a_jtag_sram_compare_row(const jtag_t* const jtag, const uint8_t* const expected, const uint8_t* const mask, const uint8_t next_address) { static bool cpld_xc2c64a_jtag_sram_compare_row(
const jtag_t* const jtag,
const uint8_t* const expected,
const uint8_t* const mask,
const uint8_t next_address)
{
/* Run-Test/Idle -> Shift-DR */ /* Run-Test/Idle -> Shift-DR */
uint8_t read[CPLD_XC2C64A_BYTES_IN_ROW]; uint8_t read[CPLD_XC2C64A_BYTES_IN_ROW];
memset(read, 0xff, sizeof(read)); memset(read, 0xff, sizeof(read));
cpld_xc2c64a_jtag_sram_read_row(jtag, &read[0], next_address); cpld_xc2c64a_jtag_sram_read_row(jtag, &read[0], next_address);
bool matched = true; bool matched = true;
if( (expected != NULL) && (mask != NULL) ) { if ((expected != NULL) && (mask != NULL)) {
for(size_t i=0; i<CPLD_XC2C64A_BYTES_IN_ROW; i++) { for (size_t i = 0; i < CPLD_XC2C64A_BYTES_IN_ROW; i++) {
const uint8_t significant_differences = (read[i] ^ expected[i]) & mask[i]; const uint8_t significant_differences =
(read[i] ^ expected[i]) & mask[i];
matched &= (significant_differences == 0); matched &= (significant_differences == 0);
} }
} }
@ -372,16 +443,19 @@ static bool cpld_xc2c64a_jtag_sram_compare_row(const jtag_t* const jtag, const u
void cpld_xc2c64a_jtag_sram_write( void cpld_xc2c64a_jtag_sram_write(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program const cpld_xc2c64a_program_t* const program)
) { {
cpld_xc2c_jtag_reset_and_idle(jtag); cpld_xc2c_jtag_reset_and_idle(jtag);
cpld_xc2c_jtag_enable(jtag); cpld_xc2c_jtag_enable(jtag);
cpld_xc2c_jtag_sram_write(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]; const uint8_t address = cpld_hackrf_row_addresses.address[row];
cpld_xc2c64a_jtag_sram_write_row(jtag, address, &program->row[row].data[0]); cpld_xc2c64a_jtag_sram_write_row(
jtag,
address,
&program->row[row].data[0]);
} }
cpld_xc2c_jtag_disable(jtag); cpld_xc2c_jtag_disable(jtag);
@ -392,8 +466,8 @@ void cpld_xc2c64a_jtag_sram_write(
bool cpld_xc2c64a_jtag_sram_verify( bool cpld_xc2c64a_jtag_sram_verify(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program, const cpld_xc2c64a_program_t* const program,
const cpld_xc2c64a_verify_t* const verify const cpld_xc2c64a_verify_t* const verify)
) { {
cpld_xc2c_jtag_reset_and_idle(jtag); cpld_xc2c_jtag_reset_and_idle(jtag);
cpld_xc2c_jtag_enable(jtag); cpld_xc2c_jtag_enable(jtag);
@ -403,13 +477,22 @@ bool cpld_xc2c64a_jtag_sram_verify(
* the first row's data. * the first row's data.
*/ */
bool matched = true; bool matched = true;
for(size_t address_row=0; address_row<=CPLD_XC2C64A_ROWS; address_row++) { for (size_t address_row = 0; address_row <= CPLD_XC2C64A_ROWS; address_row++) {
const int data_row = (int)address_row - 1; const int data_row = (int) address_row - 1;
const size_t mask_index = (data_row >= 0) ? verify->mask_index[data_row] : 0; const size_t mask_index =
const uint8_t* const expected = (data_row >= 0) ? &program->row[data_row].data[0] : NULL; (data_row >= 0) ? verify->mask_index[data_row] : 0;
const uint8_t* const mask = (data_row >= 0) ? &verify->mask[mask_index].value[0] : NULL; const uint8_t* const expected =
const uint8_t next_address = (address_row < CPLD_XC2C64A_ROWS) ? cpld_hackrf_row_addresses.address[address_row] : 0; (data_row >= 0) ? &program->row[data_row].data[0] : NULL;
matched &= cpld_xc2c64a_jtag_sram_compare_row(jtag, expected, mask, next_address); const uint8_t* const mask =
(data_row >= 0) ? &verify->mask[mask_index].value[0] : NULL;
const uint8_t next_address = (address_row < CPLD_XC2C64A_ROWS) ?
cpld_hackrf_row_addresses.address[address_row] :
0;
matched &= cpld_xc2c64a_jtag_sram_compare_row(
jtag,
expected,
mask,
next_address);
} }
cpld_xc2c_jtag_disable(jtag); cpld_xc2c_jtag_disable(jtag);

View File

@ -28,8 +28,8 @@
#include "cpld_jtag.h" #include "cpld_jtag.h"
/* Xilinx CoolRunner II XC2C64A bitstream attributes */ /* Xilinx CoolRunner II XC2C64A bitstream attributes */
#define CPLD_XC2C64A_ROWS (98) #define CPLD_XC2C64A_ROWS (98)
#define CPLD_XC2C64A_BITS_IN_ROW (274) #define CPLD_XC2C64A_BITS_IN_ROW (274)
#define CPLD_XC2C64A_BYTES_IN_ROW ((CPLD_XC2C64A_BITS_IN_ROW + 7) / 8) #define CPLD_XC2C64A_BYTES_IN_ROW ((CPLD_XC2C64A_BITS_IN_ROW + 7) / 8)
typedef struct { typedef struct {
@ -56,20 +56,17 @@ typedef struct {
bool cpld_xc2c64a_jtag_checksum( bool cpld_xc2c64a_jtag_checksum(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_verify_t* const verify, const cpld_xc2c64a_verify_t* const verify,
uint32_t* const crc_value uint32_t* const crc_value);
);
void cpld_xc2c64a_jtag_sram_write( void cpld_xc2c64a_jtag_sram_write(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program const cpld_xc2c64a_program_t* const program);
);
bool cpld_xc2c64a_jtag_sram_verify( bool cpld_xc2c64a_jtag_sram_verify(
const jtag_t* const jtag, const jtag_t* const jtag,
const cpld_xc2c64a_program_t* const program, const cpld_xc2c64a_program_t* const program,
const cpld_xc2c64a_verify_t* const verify const cpld_xc2c64a_verify_t* const verify);
);
extern const cpld_xc2c64a_program_t cpld_hackrf_program_sram; extern const cpld_xc2c64a_program_t cpld_hackrf_program_sram;
extern const cpld_xc2c64a_verify_t cpld_hackrf_verify; extern const cpld_xc2c64a_verify_t cpld_hackrf_verify;
extern const cpld_xc2c64a_row_addresses_t cpld_hackrf_row_addresses; 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> #include <stdbool.h>
void crc32_init(crc32_t* const crc) { void crc32_init(crc32_t* const crc)
{
crc->remainder = 0xffffffff; crc->remainder = 0xffffffff;
crc->reversed_polynomial = 0xedb88320; crc->reversed_polynomial = 0xedb88320;
crc->final_xor = 0xffffffff; crc->final_xor = 0xffffffff;
} }
void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t byte_count) { void crc32_update(crc32_t* const crc, const uint8_t* const data, const size_t byte_count)
{
uint32_t remainder = crc->remainder; uint32_t remainder = crc->remainder;
const size_t bit_count = byte_count * 8; const size_t bit_count = byte_count * 8;
for(size_t bit_n=0; bit_n<bit_count; bit_n++) { for (size_t bit_n = 0; bit_n < bit_count; bit_n++) {
const bool bit_in = data[bit_n >> 3] & (1 << (bit_n & 7)); const bool bit_in = data[bit_n >> 3] & (1 << (bit_n & 7));
remainder ^= (bit_in ? 1 : 0); remainder ^= (bit_in ? 1 : 0);
const bool bit_out = (remainder & 1); const bool bit_out = (remainder & 1);
remainder >>= 1; remainder >>= 1;
if( bit_out ) { if (bit_out) {
remainder ^= crc->reversed_polynomial; remainder ^= crc->reversed_polynomial;
} }
} }
crc->remainder = remainder; crc->remainder = remainder;
} }
uint32_t crc32_digest(const crc32_t* const crc) { uint32_t crc32_digest(const crc32_t* const crc)
{
return crc->remainder ^ crc->final_xor; return crc->remainder ^ crc->final_xor;
} }

View File

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

View File

@ -30,6 +30,7 @@
// structures are supposedly the same between processors (to an // structures are supposedly the same between processors (to an
// undetermined extent). // undetermined extent).
typedef struct armv7m_scb_t armv7m_scb_t; typedef struct armv7m_scb_t armv7m_scb_t;
struct armv7m_scb_t { struct armv7m_scb_t {
volatile const uint32_t CPUID; volatile const uint32_t CPUID;
volatile uint32_t ICSR; volatile uint32_t ICSR;
@ -64,10 +65,10 @@ struct armv7m_scb_t {
volatile uint32_t CPACR; volatile uint32_t CPACR;
} __attribute__((packed)); } __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_DEBUGEVT (1 << 31)
#define SCB_HFSR_FORCED (1 << 30) #define SCB_HFSR_FORCED (1 << 30)
#define SCB_HFSR_VECTTBL (1 << 1) #define SCB_HFSR_VECTTBL (1 << 1)
#endif//__FAULT_HANDLER__ #endif //__FAULT_HANDLER__

View File

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

View File

@ -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_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); 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); void gpio_write(gpio_t gpio, const bool value);
bool gpio_read(gpio_t gpio); bool gpio_read(gpio_t gpio);
#endif/*__GPIO_H__*/ #endif /*__GPIO_H__*/

View File

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

View File

@ -32,19 +32,19 @@
*/ */
typedef struct gpio_port_t { typedef struct gpio_port_t {
volatile uint32_t dir; /* +0x000 */ volatile uint32_t dir; /* +0x000 */
uint32_t _reserved0[31]; uint32_t _reserved0[31];
volatile uint32_t mask; /* +0x080 */ volatile uint32_t mask; /* +0x080 */
uint32_t _reserved1[31]; uint32_t _reserved1[31];
volatile uint32_t pin; /* +0x100 */ volatile uint32_t pin; /* +0x100 */
uint32_t _reserved2[31]; uint32_t _reserved2[31];
volatile uint32_t mpin; /* +0x180 */ volatile uint32_t mpin; /* +0x180 */
uint32_t _reserved3[31]; uint32_t _reserved3[31];
volatile uint32_t set; /* +0x200 */ volatile uint32_t set; /* +0x200 */
uint32_t _reserved4[31]; uint32_t _reserved4[31];
volatile uint32_t clr; /* +0x280 */ volatile uint32_t clr; /* +0x280 */
uint32_t _reserved5[31]; uint32_t _reserved5[31];
volatile uint32_t not; /* +0x300 */ volatile uint32_t not ; /* +0x300 */
} gpio_port_t; } gpio_port_t;
struct gpio_t { struct gpio_t {
@ -53,13 +53,15 @@ struct gpio_t {
volatile uint32_t* const gpio_w; volatile uint32_t* const gpio_w;
}; };
#define GPIO_LPC_BASE (0x400f4000) #define GPIO_LPC_BASE (0x400f4000)
#define GPIO_LPC_B_OFFSET (0x0) #define GPIO_LPC_B_OFFSET (0x0)
#define GPIO_LPC_W_OFFSET (0x1000) #define GPIO_LPC_W_OFFSET (0x1000)
#define GPIO_LPC_PORT_OFFSET (0x2000) #define GPIO_LPC_PORT_OFFSET (0x2000)
#define GPIO_LPC_PORT(_n) ((gpio_port_t*)((GPIO_LPC_BASE + GPIO_LPC_PORT_OFFSET) + (_n) * 4)) #define GPIO_LPC_PORT(_n) \
#define GPIO_LPC_W(_port_num, _pin_num) (volatile uint32_t*)((GPIO_LPC_BASE + GPIO_LPC_W_OFFSET) + ((_port_num) * 0x80) + ((_pin_num) * 4)) ((gpio_port_t*) ((GPIO_LPC_BASE + GPIO_LPC_PORT_OFFSET) + (_n) *4))
#define GPIO_LPC_W(_port_num, _pin_num) \
(volatile uint32_t*) ((GPIO_LPC_BASE + GPIO_LPC_W_OFFSET) + ((_port_num) *0x80) + ((_pin_num) *4))
// clang-format off // clang-format off
#define GPIO(_port_num, _pin_num) { \ #define GPIO(_port_num, _pin_num) { \
@ -69,4 +71,4 @@ struct gpio_t {
} }
// clang-format on // clang-format on
#endif/*__GPIO_LPC_H__*/ #endif /*__GPIO_LPC_H__*/

View File

@ -41,18 +41,18 @@
#include <libopencm3/lpc43xx/ssp.h> #include <libopencm3/lpc43xx/ssp.h>
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
#include "portapack.h" #include "portapack.h"
#endif #endif
#include "gpio_lpc.h" #include "gpio_lpc.h"
/* GPIO Output PinMux */ /* GPIO Output PinMux */
static struct gpio_t gpio_led[] = { static struct gpio_t gpio_led[] = {
GPIO(2, 1), GPIO(2, 1),
GPIO(2, 2), GPIO(2, 2),
GPIO(2, 8), GPIO(2, 8),
#ifdef RAD1O #ifdef RAD1O
GPIO(5, 26), GPIO(5, 26),
#endif #endif
}; };
@ -139,14 +139,14 @@ static struct gpio_t gpio_rx_q_invert = GPIO(0, 13);
// clang-format on // clang-format on
i2c_bus_t i2c0 = { i2c_bus_t i2c0 = {
.obj = (void*)I2C0_BASE, .obj = (void*) I2C0_BASE,
.start = i2c_lpc_start, .start = i2c_lpc_start,
.stop = i2c_lpc_stop, .stop = i2c_lpc_stop,
.transfer = i2c_lpc_transfer, .transfer = i2c_lpc_transfer,
}; };
i2c_bus_t i2c1 = { i2c_bus_t i2c1 = {
.obj = (void*)I2C1_BASE, .obj = (void*) I2C1_BASE,
.start = i2c_lpc_start, .start = i2c_lpc_start,
.stop = i2c_lpc_stop, .stop = i2c_lpc_stop,
.transfer = i2c_lpc_transfer, .transfer = i2c_lpc_transfer,
@ -194,7 +194,7 @@ const ssp_config_t ssp_config_max5864 = {
}; };
spi_bus_t spi_bus_ssp1 = { spi_bus_t spi_bus_ssp1 = {
.obj = (void*)SSP1_BASE, .obj = (void*) SSP1_BASE,
.config = &ssp_config_max2837, .config = &ssp_config_max2837,
.start = spi_ssp_start, .start = spi_ssp_start,
.stop = spi_ssp_stop, .stop = spi_ssp_stop,
@ -224,7 +224,7 @@ const ssp_config_t ssp_config_w25q80bv = {
}; };
spi_bus_t spi_bus_ssp0 = { spi_bus_t spi_bus_ssp0 = {
.obj = (void*)SSP0_BASE, .obj = (void*) SSP0_BASE,
.config = &ssp_config_w25q80bv, .config = &ssp_config_w25q80bv,
.start = spi_ssp_start, .start = spi_ssp_start,
.stop = spi_ssp_stop, .stop = spi_ssp_stop,
@ -304,38 +304,35 @@ void delay_us_at_mhz(uint32_t us, uint32_t mhz)
{ {
// The loop below takes 4 cycles per iteration. // The loop below takes 4 cycles per iteration.
uint32_t loop_iterations = (us * mhz) / 4; uint32_t loop_iterations = (us * mhz) / 4;
asm volatile ( asm volatile("start%=:\n"
"start%=:\n" " subs %[ITERATIONS], #1\n" // 1 cycle
" subs %[ITERATIONS], #1\n" // 1 cycle " bpl start%=\n" // 3 cycles
" bpl start%=\n" // 3 cycles :
: : [ITERATIONS] "r"(loop_iterations));
: [ITERATIONS] "r" (loop_iterations)
);
} }
/* GCD algo from wikipedia */ /* GCD algo from wikipedia */
/* http://en.wikipedia.org/wiki/Greatest_common_divisor */ /* http://en.wikipedia.org/wiki/Greatest_common_divisor */
static uint32_t static uint32_t gcd(uint32_t u, uint32_t v)
gcd(uint32_t u, uint32_t v)
{ {
int s; int s;
if (!u || !v) if (!u || !v)
return u | v; return u | v;
for (s=0; !((u|v)&1); s++) { for (s = 0; !((u | v) & 1); s++) {
u >>= 1; u >>= 1;
v >>= 1; v >>= 1;
} }
while (!(u&1)) while (!(u & 1))
u >>= 1; u >>= 1;
do { do {
while (!(v&1)) while (!(v & 1))
v >>= 1; v >>= 1;
if (u>v) { if (u > v) {
uint32_t t; uint32_t t;
t = v; t = v;
v = u; v = u;
@ -343,8 +340,7 @@ gcd(uint32_t u, uint32_t v)
} }
v = v - u; v = v - u;
} } while (v);
while (v);
return u << s; return u << s;
} }
@ -352,11 +348,11 @@ gcd(uint32_t u, uint32_t v)
bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom) bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
{ {
const uint64_t VCO_FREQ = 800 * 1000 * 1000; /* 800 MHz */ 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 a, b, c;
uint32_t rem; uint32_t rem;
hackrf_ui()->set_sample_rate(rate_num/2); hackrf_ui()->set_sample_rate(rate_num / 2);
/* Find best config */ /* Find best config */
a = (VCO_FREQ * rate_denom) / rate_num; a = (VCO_FREQ * rate_denom) / rate_num;
@ -373,14 +369,14 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
rem /= g; rem /= g;
rate_num /= g; rate_num /= g;
if (rate_num < (1<<20)) { if (rate_num < (1 << 20)) {
/* Perfect match */ /* Perfect match */
b = rem; b = rem;
c = rate_num; c = rate_num;
} else { } else {
/* Approximate */ /* Approximate */
c = (1<<20) - 1; c = (1 << 20) - 1;
b = ((uint64_t)c * (uint64_t)rem) / rate_num; b = ((uint64_t) c * (uint64_t) rem) / rate_num;
g = gcd(b, c); g = gcd(b, c);
b /= g; b /= g;
@ -389,11 +385,11 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
} }
bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config); bool streaming = sgpio_cpld_stream_is_enabled(&sgpio_config);
if (streaming) { if (streaming) {
sgpio_cpld_stream_disable(&sgpio_config); sgpio_cpld_stream_disable(&sgpio_config);
} }
/* Can we enable integer mode ? */ /* Can we enable integer mode ? */
if (a & 0x1 || b) if (a & 0x1 || b)
si5351c_set_int_mode(&clock_gen, 0, 0); si5351c_set_int_mode(&clock_gen, 0, 0);
@ -401,18 +397,18 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
si5351c_set_int_mode(&clock_gen, 0, 1); si5351c_set_int_mode(&clock_gen, 0, 1);
/* Final MS values */ /* Final MS values */
MSx_P1 = 128*a + (128 * b/c) - 512; MSx_P1 = 128 * a + (128 * b / c) - 512;
MSx_P2 = (128*b) % c; MSx_P2 = (128 * b) % c;
MSx_P3 = c; MSx_P3 = c;
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1); si5351c_configure_multisynth(&clock_gen, 0, MSx_P1, MSx_P2, MSx_P3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ /* 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) */ /* 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) { if (streaming) {
sgpio_cpld_stream_enable(&sgpio_config); sgpio_cpld_stream_enable(&sgpio_config);
@ -421,73 +417,76 @@ bool sample_rate_frac_set(uint32_t rate_num, uint32_t rate_denom)
return true; return true;
} }
bool sample_rate_set(const uint32_t sample_rate_hz) { bool sample_rate_set(const uint32_t sample_rate_hz)
{
uint32_t p1 = 4608; uint32_t p1 = 4608;
uint32_t p2 = 0; uint32_t p2 = 0;
uint32_t p3 = 0; uint32_t p3 = 0;
switch(sample_rate_hz) { switch (sample_rate_hz) {
case 8000000: 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; break;
case 9216000:
// 43.40277777777778: a = 43; b = 29; c = 72
p1 = 5043;
p2 = 40;
p3 = 72;
break;
case 10000000: case 9216000:
p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec) // 43.40277777777778: a = 43; b = 29; c = 72
break; p1 = 5043;
p2 = 40;
case 12288000: p3 = 72;
// 32.552083333333336: a = 32; b = 159; c = 288 break;
p1 = 3654;
p2 = 192;
p3 = 288;
break;
case 12500000: case 10000000:
p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec) p1 = SI_INTDIV(40); // 800MHz / 40 = 20 MHz (SGPIO), 10 MHz (codec)
break; break;
case 16000000: case 12288000:
p1 = SI_INTDIV(25); // 800MHz / 25 = 32 MHz (SGPIO), 16 MHz (codec) // 32.552083333333336: a = 32; b = 159; c = 288
break; p1 = 3654;
p2 = 192;
case 18432000: p3 = 288;
// 21.70138888889: a = 21; b = 101; c = 144 break;
p1 = 2265;
p2 = 112; case 12500000:
p3 = 144; p1 = SI_INTDIV(32); // 800MHz / 32 = 25 MHz (SGPIO), 12.5 MHz (codec)
break; 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: default:
return false; return false;
} }
/* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */ /* MS0/CLK0 is the source for the MAX5864/CPLD (CODEC_CLK). */
si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1); si5351c_configure_multisynth(&clock_gen, 0, p1, p2, p3, 1);
/* MS0/CLK1 is the source for the CPLD (CODEC_X2_CLK). */ /* 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) */ /* 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; return true;
} }
bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz) { bool baseband_filter_bandwidth_set(const uint32_t bandwidth_hz)
{
uint32_t bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz); uint32_t bandwidth_hz_real = max2837_set_lpf_bandwidth(&max2837, bandwidth_hz);
if(bandwidth_hz_real) hackrf_ui()->set_filter_bw(bandwidth_hz_real); if (bandwidth_hz_real)
hackrf_ui()->set_filter_bw(bandwidth_hz_real);
return bandwidth_hz_real != 0; return bandwidth_hz_real != 0;
} }
@ -507,8 +506,7 @@ static void cpu_clock_pll1_max_speed(void)
/* 1. Select the IRC as BASE_M4_CLK source. */ /* 1. Select the IRC as BASE_M4_CLK source. */
reg_val = CGU_BASE_M4_CLK; reg_val = CGU_BASE_M4_CLK;
reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK; reg_val &= ~CGU_BASE_M4_CLK_CLK_SEL_MASK;
reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | reg_val |= CGU_BASE_M4_CLK_CLK_SEL(CGU_SRC_IRC) | CGU_BASE_M4_CLK_AUTOBLOCK(1);
CGU_BASE_M4_CLK_AUTOBLOCK(1);
CGU_BASE_M4_CLK = reg_val; CGU_BASE_M4_CLK = reg_val;
/* 2. Enable the crystal oscillator. */ /* 2. Enable the crystal oscillator. */
@ -563,7 +561,7 @@ static void cpu_clock_pll1_max_speed(void)
} }
/* clock startup for LPC4320 configure PLL1 to max speed (204MHz). /* 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) void cpu_clock_init(void)
{ {
/* use IRC as clock source for APB1 (including I2C0) */ /* use IRC as clock source for APB1 (including I2C0) */
@ -595,9 +593,21 @@ void cpu_clock_init(void)
*/ */
/* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */ /* MS4/CLK4 is the source for the RFFC5071 mixer (MAX2837 on rad1o). */
si5351c_configure_multisynth(&clock_gen, 4, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */ si5351c_configure_multisynth(
/* MS5/CLK5 is the source for the MAX2837 clock input (MAX2871 on rad1o). */ &clock_gen,
si5351c_configure_multisynth(&clock_gen, 5, 20*128-512, 0, 1, 0); /* 800/20 = 40MHz */ 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. */ /* MS6/CLK6 is unused. */
/* MS7/CLK7 is unused. */ /* MS7/CLK7 is unused. */
@ -628,53 +638,51 @@ void cpu_clock_init(void)
cpu_clock_pll1_max_speed(); cpu_clock_pll1_max_speed();
/* use XTAL_OSC as clock source for APB1 */ /* use XTAL_OSC as clock source for APB1 */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1) CGU_BASE_APB1_CLK =
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL); CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_XTAL);
/* use XTAL_OSC as clock source for APB3 */ /* use XTAL_OSC as clock source for APB3 */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1) CGU_BASE_APB3_CLK =
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL); CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_XTAL);
/* use XTAL_OSC as clock source for PLL0USB */ /* use XTAL_OSC as clock source for PLL0USB */
CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) CGU_PLL0USB_CTRL = CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_AUTOBLOCK(1) |
| CGU_PLL0USB_CTRL_AUTOBLOCK(1) CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL);
| CGU_PLL0USB_CTRL_CLK_SEL(CGU_SRC_XTAL);
while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {} while (CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK) {}
/* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */ /* configure PLL0USB to produce 480 MHz clock from 12 MHz XTAL_OSC */
/* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */ /* Values from User Manual v1.4 Table 94, for 12MHz oscillator. */
CGU_PLL0USB_MDIV = 0x06167FFA; CGU_PLL0USB_MDIV = 0x06167FFA;
CGU_PLL0USB_NP_DIV = 0x00302062; CGU_PLL0USB_NP_DIV = 0x00302062;
CGU_PLL0USB_CTRL |= (CGU_PLL0USB_CTRL_PD(1) CGU_PLL0USB_CTRL |=
| CGU_PLL0USB_CTRL_DIRECTI(1) (CGU_PLL0USB_CTRL_PD(1) | CGU_PLL0USB_CTRL_DIRECTI(1) |
| CGU_PLL0USB_CTRL_DIRECTO(1) CGU_PLL0USB_CTRL_DIRECTO(1) | CGU_PLL0USB_CTRL_CLKEN(1));
| CGU_PLL0USB_CTRL_CLKEN(1));
/* power on PLL0USB and wait until stable */ /* power on PLL0USB and wait until stable */
CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK; CGU_PLL0USB_CTRL &= ~CGU_PLL0USB_CTRL_PD_MASK;
while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {} while (!(CGU_PLL0USB_STAT & CGU_PLL0USB_STAT_LOCK_MASK)) {}
/* use PLL0USB as clock source for USB0 */ /* use PLL0USB as clock source for USB0 */
CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) CGU_BASE_USB0_CLK = CGU_BASE_USB0_CLK_AUTOBLOCK(1) |
| CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB); CGU_BASE_USB0_CLK_CLK_SEL(CGU_SRC_PLL0USB);
/* Switch peripheral clock over to use PLL1 (204MHz) */ /* Switch peripheral clock over to use PLL1 (204MHz) */
CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) CGU_BASE_PERIPH_CLK = CGU_BASE_PERIPH_CLK_AUTOBLOCK(1) |
| CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_PERIPH_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB1 clock over to use PLL1 (204MHz) */ /* Switch APB1 clock over to use PLL1 (204MHz) */
CGU_BASE_APB1_CLK = CGU_BASE_APB1_CLK_AUTOBLOCK(1) CGU_BASE_APB1_CLK =
| CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_APB1_CLK_AUTOBLOCK(1) | CGU_BASE_APB1_CLK_CLK_SEL(CGU_SRC_PLL1);
/* Switch APB3 clock over to use PLL1 (204MHz) */ /* Switch APB3 clock over to use PLL1 (204MHz) */
CGU_BASE_APB3_CLK = CGU_BASE_APB3_CLK_AUTOBLOCK(1) CGU_BASE_APB3_CLK =
| CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_APB3_CLK_AUTOBLOCK(1) | CGU_BASE_APB3_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_SSP0_CLK = CGU_BASE_SSP0_CLK_AUTOBLOCK(1) CGU_BASE_SSP0_CLK =
| CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_SSP0_CLK_AUTOBLOCK(1) | CGU_BASE_SSP0_CLK_CLK_SEL(CGU_SRC_PLL1);
CGU_BASE_SSP1_CLK = CGU_BASE_SSP1_CLK_AUTOBLOCK(1) CGU_BASE_SSP1_CLK =
| CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1); CGU_BASE_SSP1_CLK_AUTOBLOCK(1) | CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1);
#if (defined JAWBREAKER || defined HACKRF_ONE) #if (defined JAWBREAKER || defined HACKRF_ONE)
/* Disable unused clocks */ /* Disable unused clocks */
@ -689,8 +697,8 @@ void cpu_clock_init(void)
CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1); CGU_IDIVE_CTRL = CGU_IDIVE_CTRL_PD(1);
/* Base clocks */ /* Base clocks */
CGU_BASE_SPIFI_CLK = CGU_BASE_SPIFI_CLK_PD(1); /* SPIFI is only used at boot */ 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_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_RX_CLK = CGU_BASE_PHY_RX_CLK_PD(1);
CGU_BASE_PHY_TX_CLK = CGU_BASE_PHY_TX_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); CGU_BASE_LCD_CLK = CGU_BASE_LCD_CLK_PD(1);
@ -749,7 +757,7 @@ clock_source_t activate_best_clock_source(void)
{ {
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
/* Ensure PortaPack reference oscillator is off while checking for external clock input. */ /* 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); portapack_reference_oscillator(false);
} }
#endif #endif
@ -762,9 +770,9 @@ clock_source_t activate_best_clock_source(void)
} else { } else {
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
/* Enable PortaPack reference oscillator (if present), and check for valid clock. */ /* 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); 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)) { if (si5351c_clkin_signal_valid(&clock_gen)) {
source = CLOCK_SOURCE_PORTAPACK; source = CLOCK_SOURCE_PORTAPACK;
} else { } else {
@ -775,7 +783,9 @@ clock_source_t activate_best_clock_source(void)
/* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */ /* No external or PortaPack clock was found. Use HackRF Si5351C crystal. */
} }
si5351c_set_clock_source(&clock_gen, (source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN); si5351c_set_clock_source(
&clock_gen,
(source == CLOCK_SOURCE_HACKRF) ? PLL_SOURCE_XTAL : PLL_SOURCE_CLKIN);
hackrf_ui()->set_clock_source(source); hackrf_ui()->set_clock_source(source);
return source; return source;
} }
@ -790,7 +800,8 @@ void ssp1_set_mode_max5864(void)
spi_bus_start(max5864.bus, &ssp_config_max5864); spi_bus_start(max5864.bus, &ssp_config_max5864);
} }
void pin_setup(void) { void pin_setup(void)
{
/* Configure all GPIO as Input (safe state) */ /* Configure all GPIO as Input (safe state) */
gpio_init(); gpio_init();
@ -809,13 +820,13 @@ void pin_setup(void) {
* LPC43xx pull-up and pull-down resistors are approximately 53K. * LPC43xx pull-up and pull-down resistors are approximately 53K.
*/ */
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
scu_pinmux(SCU_PINMUX_PP_TMS, SCU_GPIO_PUP | 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); scu_pinmux(SCU_PINMUX_PP_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
#endif #endif
scu_pinmux(SCU_PINMUX_CPLD_TMS, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0); 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_TDI, SCU_GPIO_NOPULL | SCU_CONF_FUNCTION0);
scu_pinmux(SCU_PINMUX_CPLD_TDO, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); 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_TCK, SCU_GPIO_PDN | SCU_CONF_FUNCTION0);
/* Configure SCU Pin Mux as GPIO */ /* Configure SCU Pin Mux as GPIO */
scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL); scu_pinmux(SCU_PINMUX_LED1, SCU_GPIO_NOPULL);
@ -874,23 +885,26 @@ void pin_setup(void) {
mixer_bus_setup(&mixer); mixer_bus_setup(&mixer);
rf_path_pin_setup(&rf_path); rf_path_pin_setup(&rf_path);
/* Configure external clock in */ /* Configure external clock in */
scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1); scu_pinmux(SCU_PINMUX_GP_CLKIN, SCU_CLK_IN | SCU_CONF_FUNCTION1);
sgpio_configure_pin_functions(&sgpio_config); sgpio_configure_pin_functions(&sgpio_config);
} }
void enable_1v8_power(void) { void enable_1v8_power(void)
{
gpio_set(&gpio_1v8_enable); gpio_set(&gpio_1v8_enable);
} }
void disable_1v8_power(void) { void disable_1v8_power(void)
{
gpio_clear(&gpio_1v8_enable); gpio_clear(&gpio_1v8_enable);
} }
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
void enable_rf_power(void) { void enable_rf_power(void)
{
uint32_t i; uint32_t i;
/* many short pulses to avoid one big voltage glitch */ /* many short pulses to avoid one big voltage glitch */
@ -901,41 +915,48 @@ void enable_rf_power(void) {
gpio_clear(&gpio_vaa_disable); gpio_clear(&gpio_vaa_disable);
} }
void disable_rf_power(void) { void disable_rf_power(void)
{
gpio_set(&gpio_vaa_disable); gpio_set(&gpio_vaa_disable);
} }
#endif #endif
#ifdef RAD1O #ifdef RAD1O
void enable_rf_power(void) { void enable_rf_power(void)
{
gpio_set(&gpio_vaa_enable); gpio_set(&gpio_vaa_enable);
} }
void disable_rf_power(void) { void disable_rf_power(void)
{
gpio_clear(&gpio_vaa_enable); gpio_clear(&gpio_vaa_enable);
} }
#endif #endif
void led_on(const led_t led) { void led_on(const led_t led)
{
gpio_set(&gpio_led[led]); gpio_set(&gpio_led[led]);
} }
void led_off(const led_t led) { void led_off(const led_t led)
{
gpio_clear(&gpio_led[led]); gpio_clear(&gpio_led[led]);
} }
void led_toggle(const led_t led) { void led_toggle(const led_t led)
{
gpio_toggle(&gpio_led[led]); gpio_toggle(&gpio_led[led]);
} }
void hw_sync_enable(const hw_sync_mode_t hw_sync_mode){ void hw_sync_enable(const hw_sync_mode_t hw_sync_mode)
gpio_write(&gpio_hw_sync_enable, hw_sync_mode==1); {
gpio_write(&gpio_hw_sync_enable, hw_sync_mode == 1);
} }
void halt_and_flash(const uint32_t duration) { void halt_and_flash(const uint32_t duration)
{
/* blink LED1, LED2, and LED3 */ /* blink LED1, LED2, and LED3 */
while (1) while (1) {
{
led_on(LED1); led_on(LED1);
led_on(LED2); led_on(LED2);
led_on(LED3); led_on(LED3);

View File

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

View File

@ -26,7 +26,7 @@
#include <stddef.h> #include <stddef.h>
#define UNUSED(x) (void)(x) #define UNUSED(x) (void) (x)
/* Stub functions for null UI function table */ /* Stub functions for null UI function table */
// clang-format off // clang-format off
@ -46,6 +46,7 @@ void hackrf_ui_set_antenna_bias_null(bool antenna_bias) { UNUSED(antenna_bias);
void hackrf_ui_set_clock_source_null(clock_source_t source) { UNUSED(source); } void hackrf_ui_set_clock_source_null(clock_source_t source) { UNUSED(source); }
void hackrf_ui_set_transceiver_mode_null(transceiver_mode_t mode) { UNUSED(mode); } void hackrf_ui_set_transceiver_mode_null(transceiver_mode_t mode) { UNUSED(mode); }
bool hackrf_ui_operacake_gpio_compatible_null(void) { return true; } bool hackrf_ui_operacake_gpio_compatible_null(void) { return true; }
// clang-format on // clang-format on
/* Null UI function table, used if there's no hardware UI detected. Eliminates the /* Null UI function table, used if there's no hardware UI detected. Eliminates the
@ -67,34 +68,35 @@ static const hackrf_ui_t hackrf_ui_null = {
&hackrf_ui_set_antenna_bias_null, &hackrf_ui_set_antenna_bias_null,
&hackrf_ui_set_clock_source_null, &hackrf_ui_set_clock_source_null,
&hackrf_ui_set_transceiver_mode_null, &hackrf_ui_set_transceiver_mode_null,
&hackrf_ui_operacake_gpio_compatible_null &hackrf_ui_operacake_gpio_compatible_null};
};
static const hackrf_ui_t* ui = NULL; static const hackrf_ui_t* ui = NULL;
static bool ui_enabled = true; static bool ui_enabled = true;
const hackrf_ui_t* hackrf_ui(void) { const hackrf_ui_t* hackrf_ui(void)
{
/* Detect on first use. If no UI hardware is detected, use a stub function table. */ /* Detect on first use. If no UI hardware is detected, use a stub function table. */
if( ui == NULL && ui_enabled ) { if (ui == NULL && ui_enabled) {
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
if( portapack_hackrf_ui_init ) { if (portapack_hackrf_ui_init) {
ui = portapack_hackrf_ui_init(); ui = portapack_hackrf_ui_init();
} }
#endif #endif
#ifdef RAD1O #ifdef RAD1O
if( rad1o_ui_setup ) { if (rad1o_ui_setup) {
ui = rad1o_ui_setup(); ui = rad1o_ui_setup();
} }
#endif #endif
} }
if( ui == NULL ) { if (ui == NULL) {
ui = &hackrf_ui_null; ui = &hackrf_ui_null;
} }
return ui; return ui;
} }
void hackrf_ui_set_enable(bool enabled) { void hackrf_ui_set_enable(bool enabled)
{
if (ui_enabled != enabled) { if (ui_enabled != enabled) {
ui_enabled = enabled; ui_enabled = enabled;
hackrf_ui()->deinit(); hackrf_ui()->deinit();

View File

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

View File

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

View File

@ -26,30 +26,35 @@
/* FIXME return i2c0 status from each function */ /* FIXME return i2c0 status from each function */
void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config) { void i2c_lpc_start(i2c_bus_t* const bus, const void* const _config)
{
const i2c_lpc_config_t* const config = _config; const i2c_lpc_config_t* const config = _config;
const uint32_t port = (uint32_t)bus->obj; const uint32_t port = (uint32_t) bus->obj;
i2c_init(port, config->duty_cycle_count); i2c_init(port, config->duty_cycle_count);
} }
void i2c_lpc_stop(i2c_bus_t* const bus) { void i2c_lpc_stop(i2c_bus_t* const bus)
const uint32_t port = (uint32_t)bus->obj; {
const uint32_t port = (uint32_t) bus->obj;
i2c_disable(port); i2c_disable(port);
} }
void i2c_lpc_transfer(i2c_bus_t* const bus, void i2c_lpc_transfer(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const data_tx, const size_t count_tx, const uint8_t* const data_tx,
uint8_t* const data_rx, const size_t count_rx const size_t count_tx,
) { uint8_t* const data_rx,
const uint32_t port = (uint32_t)bus->obj; const size_t count_rx)
{
const uint32_t port = (uint32_t) bus->obj;
size_t i; size_t i;
bool ack = false; bool ack = false;
if (data_tx && (count_tx > 0)) { if (data_tx && (count_tx > 0)) {
i2c_tx_start(port); i2c_tx_start(port);
i2c_tx_byte(port, (peripheral_address << 1) | I2C_WRITE); 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]); 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)) { if (data_rx && (count_rx > 0)) {
i2c_tx_start(port); i2c_tx_start(port);
i2c_tx_byte(port, (peripheral_address << 1) | I2C_READ); 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 each byte except the last */
ack = (i!=count_rx-1); ack = (i != count_rx - 1);
data_rx[i] = i2c_rx_byte(port, ack); data_rx[i] = i2c_rx_byte(port, ack);
} }
} }
@ -67,8 +72,9 @@ void i2c_lpc_transfer(i2c_bus_t* const bus,
i2c_stop(port); i2c_stop(port);
} }
bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address) { bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address)
const uint32_t port = (uint32_t)bus->obj; {
const uint32_t port = (uint32_t) bus->obj;
i2c_tx_start(port); i2c_tx_start(port);
i2c_tx_byte(port, (device_address << 1) | I2C_WRITE); 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_start(i2c_bus_t* const bus, const void* const config);
void i2c_lpc_stop(i2c_bus_t* const bus); void i2c_lpc_stop(i2c_bus_t* const bus);
void i2c_lpc_transfer(i2c_bus_t* const bus, void i2c_lpc_transfer(
i2c_bus_t* const bus,
const uint_fast8_t peripheral_address, const uint_fast8_t peripheral_address,
const uint8_t* const data_tx, const size_t count_tx, const uint8_t* const data_tx,
uint8_t* const data_rx, const size_t count_rx const size_t count_tx,
); uint8_t* const data_rx,
const size_t count_rx);
bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address); bool i2c_probe(i2c_bus_t* const bus, const uint_fast8_t device_address);
#endif/*__I2C_LPC_H__*/ #endif /*__I2C_LPC_H__*/

View File

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

View File

@ -34,44 +34,44 @@
#include "max2837_regs.def" // private register def macros #include "max2837_regs.def" // private register def macros
/* Default register values. */ /* Default register values. */
static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = { static const uint16_t max2837_regs_default[MAX2837_NUM_REGS] = {
0x150, /* 0 */ 0x150, /* 0 */
0x002, /* 1 */ 0x002, /* 1 */
0x1f4, /* 2 */ 0x1f4, /* 2 */
0x1b9, /* 3 */ 0x1b9, /* 3 */
0x00a, /* 4 */ 0x00a, /* 4 */
0x080, /* 5 */ 0x080, /* 5 */
0x006, /* 6 */ 0x006, /* 6 */
0x000, /* 7 */ 0x000, /* 7 */
0x080, /* 8 */ 0x080, /* 8 */
0x018, /* 9 */ 0x018, /* 9 */
0x058, /* 10 */ 0x058, /* 10 */
0x016, /* 11 */ 0x016, /* 11 */
0x24f, /* 12 */ 0x24f, /* 12 */
0x150, /* 13 */ 0x150, /* 13 */
0x1c5, /* 14 */ 0x1c5, /* 14 */
0x081, /* 15 */ 0x081, /* 15 */
0x01c, /* 16 */ 0x01c, /* 16 */
0x155, /* 17 */ 0x155, /* 17 */
0x155, /* 18 */ 0x155, /* 18 */
0x153, /* 19 */ 0x153, /* 19 */
0x241, /* 20 */ 0x241, /* 20 */
/* /*
* Charge Pump Common Mode Enable bit (0) of register 21 must be set or TX * 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 * 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). * page 21 says it should be set by default (0x02d).
*/ */
0x02d, /* 21 */ 0x02d, /* 21 */
0x1a9, /* 22 */ 0x1a9, /* 22 */
0x24f, /* 23 */ 0x24f, /* 23 */
0x180, /* 24 */ 0x180, /* 24 */
0x100, /* 25 */ 0x100, /* 25 */
0x3ca, /* 26 */ 0x3ca, /* 26 */
0x3e3, /* 27 */ 0x3e3, /* 27 */
0x0c0, /* 28 */ 0x0c0, /* 28 */
0x3f0, /* 29 */ 0x3f0, /* 29 */
0x080, /* 30 */ 0x080, /* 30 */
0x000 }; /* 31 */ 0x000}; /* 31 */
/* Set up all registers according to defaults specified in docs. */ /* Set up all registers according to defaults specified in docs. */
static void max2837_init(max2837_driver_t* const drv) 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) void max2837_setup(max2837_driver_t* const drv)
{ {
max2837_init(drv); max2837_init(drv);
/* Use SPI control instead of B1-B7 pins for gain settings. */ /* Use SPI control instead of B1-B7 pins for gain settings. */
set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1); set_MAX2837_TXVGA_GAIN_SPI_EN(drv, 1);
set_MAX2837_TXVGA_GAIN_MSB_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); max2837_regs_commit(drv);
} }
static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r) { static uint16_t max2837_read(max2837_driver_t* const drv, uint8_t r)
{
uint16_t value = (1 << 15) | (r << 10); uint16_t value = (1 << 15) | (r << 10);
spi_bus_transfer(drv->bus, &value, 1); spi_bus_transfer(drv->bus, &value, 1);
return value & 0x3ff; return value & 0x3ff;
} }
static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v) { static void max2837_write(max2837_driver_t* const drv, uint8_t r, uint16_t v)
{
uint16_t value = (r << 10) | (v & 0x3ff); uint16_t value = (r << 10) | (v & 0x3ff);
spi_bus_transfer(drv->bus, &value, 1); spi_bus_transfer(drv->bus, &value, 1);
} }
@ -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) void max2837_regs_commit(max2837_driver_t* const drv)
{ {
int r; int r;
for(r = 0; r < MAX2837_NUM_REGS; r++) { for (r = 0; r < MAX2837_NUM_REGS; r++) {
if ((drv->regs_dirty >> r) & 0x1) { if ((drv->regs_dirty >> r) & 0x1) {
max2837_reg_commit(drv, r); 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); drv->set_mode(drv, new_mode);
} }
max2837_mode_t max2837_mode(max2837_driver_t* const drv) { max2837_mode_t max2837_mode(max2837_driver_t* const drv)
{
return drv->mode; return drv->mode;
} }
@ -210,16 +214,13 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq)
if (freq < 2400000000U) { if (freq < 2400000000U) {
band = MAX2837_LOGEN_BSW_2_3; band = MAX2837_LOGEN_BSW_2_3;
lna_band = MAX2837_LNAband_2_4; lna_band = MAX2837_LNAband_2_4;
} } else if (freq < 2500000000U) {
else if (freq < 2500000000U) {
band = MAX2837_LOGEN_BSW_2_4; band = MAX2837_LOGEN_BSW_2_4;
lna_band = MAX2837_LNAband_2_4; lna_band = MAX2837_LNAband_2_4;
} } else if (freq < 2600000000U) {
else if (freq < 2600000000U) {
band = MAX2837_LOGEN_BSW_2_5; band = MAX2837_LOGEN_BSW_2_5;
lna_band = MAX2837_LNAband_2_6; lna_band = MAX2837_LNAband_2_6;
} } else {
else {
band = MAX2837_LOGEN_BSW_2_6; band = MAX2837_LOGEN_BSW_2_6;
lna_band = MAX2837_LNAband_2_6; lna_band = MAX2837_LNAband_2_6;
} }
@ -229,7 +230,7 @@ void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq)
div_rem = freq % 30000000; div_rem = freq % 30000000;
div_frac = 0; div_frac = 0;
div_cmp = 30000000; div_cmp = 30000000;
for( i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {
div_frac <<= 1; div_frac <<= 1;
div_cmp >>= 1; div_cmp >>= 1;
if (div_rem > div_cmp) { if (div_rem > div_cmp) {

View File

@ -30,7 +30,7 @@
#include "spi_bus.h" #include "spi_bus.h"
/* 32 registers, each containing 10 bits of data. */ /* 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 #define MAX2837_DATA_REGS_MAX_VALUE 1024
typedef enum { 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 /* Set frequency in Hz. Frequency setting is a multi-step function
* where order of register writes matters. */ * where order of register writes matters. */
extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq); extern void max2837_set_frequency(max2837_driver_t* const drv, uint32_t freq);
uint32_t max2837_set_lpf_bandwidth(max2837_driver_t* const drv, const uint32_t bandwidth_hz); uint32_t max2837_set_lpf_bandwidth(
max2837_driver_t* const drv,
const uint32_t bandwidth_hz);
bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db); bool max2837_set_lna_gain(max2837_driver_t* const drv, const uint32_t gain_db);
bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db); bool max2837_set_vga_gain(max2837_driver_t* const drv, const uint32_t gain_db);
bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db); bool max2837_set_txvga_gain(max2837_driver_t* const drv, const uint32_t gain_db);
extern void max2837_tx(max2837_driver_t* const drv); extern void max2837_tx(max2837_driver_t* const drv);
extern void max2837_rx(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 <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h" #include "hackrf_core.h"
void max2837_target_init(max2837_driver_t* const drv) { void max2837_target_init(max2837_driver_t* const drv)
{
/* Configure SSP1 Peripheral (to be moved later in SSP driver) */ /* Configure SSP1 Peripheral (to be moved later in SSP driver) */
scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
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); 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); gpio_output(drv->gpio_tx_enable);
} }
void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode) { void max2837_target_set_mode(max2837_driver_t* const drv, const max2837_mode_t new_mode)
{
/* MAX2837_MODE_SHUTDOWN: /* MAX2837_MODE_SHUTDOWN:
* All circuit blocks are powered down, except the 4-wire serial bus * All circuit blocks are powered down, except the 4-wire serial bus
* and its internal programmable registers. * and its internal programmable registers.

View File

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

View File

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

View File

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

View File

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

View File

@ -24,13 +24,14 @@
#include <libopencm3/lpc43xx/scu.h> #include <libopencm3/lpc43xx/scu.h>
#include "hackrf_core.h" #include "hackrf_core.h"
void max5864_target_init(max5864_driver_t* const drv) { void max5864_target_init(max5864_driver_t* const drv)
(void)drv; {
(void) drv;
/* Configure SSP1 Peripheral (to be moved later in SSP driver) */ /* Configure SSP1 Peripheral (to be moved later in SSP driver) */
scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP1_COPI, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
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 * 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); void max5864_target_init(max5864_driver_t* const drv);
#endif/*__MAX5864_TARGET_H__*/ #endif /*__MAX5864_TARGET_H__*/

View File

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

View File

@ -30,14 +30,14 @@
/* /*
* I2C Mode * I2C Mode
*/ */
#define OPERACAKE_PIN_OE(x) (x<<7) #define OPERACAKE_PIN_OE(x) (x << 7)
#define OPERACAKE_PIN_U2CTRL1(x) (x<<6) #define OPERACAKE_PIN_U2CTRL1(x) (x << 6)
#define OPERACAKE_PIN_U2CTRL0(x) (x<<5) #define OPERACAKE_PIN_U2CTRL0(x) (x << 5)
#define OPERACAKE_PIN_U3CTRL1(x) (x<<4) #define OPERACAKE_PIN_U3CTRL1(x) (x << 4)
#define OPERACAKE_PIN_U3CTRL0(x) (x<<3) #define OPERACAKE_PIN_U3CTRL0(x) (x << 3)
#define OPERACAKE_PIN_U1CTRL(x) (x<<2) #define OPERACAKE_PIN_U1CTRL(x) (x << 2)
#define OPERACAKE_PIN_LEDEN2(x) (x<<1) #define OPERACAKE_PIN_LEDEN2(x) (x << 1)
#define OPERACAKE_PIN_LEDEN(x) (x<<0) #define OPERACAKE_PIN_LEDEN(x) (x << 0)
#define OPERACAKE_PORT_A1 (OPERACAKE_PIN_U2CTRL0(0) | OPERACAKE_PIN_U2CTRL1(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)) #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_B3 (OPERACAKE_PIN_U3CTRL0(0) | OPERACAKE_PIN_U3CTRL1(1))
#define OPERACAKE_PORT_B4 (OPERACAKE_PIN_U3CTRL0(1) | 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_SAMESIDE OPERACAKE_PIN_U1CTRL(1)
#define OPERACAKE_CROSSOVER OPERACAKE_PIN_U1CTRL(0) #define OPERACAKE_CROSSOVER OPERACAKE_PIN_U1CTRL(0)
#define OPERACAKE_EN_LEDS (OPERACAKE_PIN_LEDEN2(1) | OPERACAKE_PIN_LEDEN2(0)) #define OPERACAKE_EN_LEDS (OPERACAKE_PIN_LEDEN2(1) | OPERACAKE_PIN_LEDEN2(0))
#define OPERACAKE_GPIO_ENABLE OPERACAKE_PIN_OE(0) #define OPERACAKE_GPIO_ENABLE OPERACAKE_PIN_OE(0)
#define OPERACAKE_GPIO_DISABLE OPERACAKE_PIN_OE(1) #define OPERACAKE_GPIO_DISABLE OPERACAKE_PIN_OE(1)
#define OPERACAKE_REG_INPUT 0x00 #define OPERACAKE_REG_INPUT 0x00
@ -60,9 +60,9 @@
#define OPERACAKE_REG_POLARITY 0x02 #define OPERACAKE_REG_POLARITY 0x02
#define OPERACAKE_REG_CONFIG 0x03 #define OPERACAKE_REG_CONFIG 0x03
#define OPERACAKE_DEFAULT_OUTPUT (OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE \ #define OPERACAKE_DEFAULT_OUTPUT \
| OPERACAKE_PORT_A1 | OPERACAKE_PORT_B1 \ (OPERACAKE_GPIO_DISABLE | OPERACAKE_SAMESIDE | OPERACAKE_PORT_A1 | \
| OPERACAKE_EN_LEDS) OPERACAKE_PORT_B1 | OPERACAKE_EN_LEDS)
#define OPERACAKE_CONFIG_ALL_OUTPUT (0x00) #define OPERACAKE_CONFIG_ALL_OUTPUT (0x00)
// Leave LED bits as outputs // Leave LED bits as outputs
#define OPERACAKE_CONFIG_GPIO_INPUTS (0x7C) #define OPERACAKE_CONFIG_GPIO_INPUTS (0x7C)
@ -80,9 +80,9 @@ static uint8_t current_range = INVALID_RANGE;
i2c_bus_t* const oc_bus = &i2c0; i2c_bus_t* const oc_bus = &i2c0;
enum operacake_switching_mode { enum operacake_switching_mode {
MODE_MANUAL = 0, MODE_MANUAL = 0,
MODE_FREQUENCY = 1, MODE_FREQUENCY = 1,
MODE_TIME = 2, MODE_TIME = 2,
}; };
struct operacake_state { struct operacake_state {
@ -96,18 +96,20 @@ struct operacake_state operacake_boards[OPERACAKE_MAX_BOARDS];
bool allow_gpio_mode = true; bool allow_gpio_mode = true;
/* read single register */ /* read single register */
uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg) { uint8_t operacake_read_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg)
{
// Convert from Opera Cake address (0-7) to I2C address // Convert from Opera Cake address (0-7) to I2C address
address += OPERACAKE_ADDRESS_DEFAULT; address += OPERACAKE_ADDRESS_DEFAULT;
const uint8_t data_tx[] = { reg }; const uint8_t data_tx[] = {reg};
uint8_t data_rx[] = { 0x00 }; uint8_t data_rx[] = {0x00};
i2c_bus_transfer(bus, address, data_tx, 1, data_rx, 1); i2c_bus_transfer(bus, address, data_tx, 1, data_rx, 1);
return data_rx[0]; return data_rx[0];
} }
/* Write to one of the PCA9557 registers */ /* Write to one of the PCA9557 registers */
void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uint8_t value) { void operacake_write_reg(i2c_bus_t* const bus, uint8_t address, uint8_t reg, uint8_t value)
{
// Convert from Opera Cake address (0-7) to I2C address // Convert from Opera Cake address (0-7) to I2C address
address += OPERACAKE_ADDRESS_DEFAULT; address += OPERACAKE_ADDRESS_DEFAULT;
@ -115,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); i2c_bus_transfer(bus, address, data, 2, NULL, 0);
} }
uint8_t operacake_init(bool allow_gpio) { uint8_t operacake_init(bool allow_gpio)
{
/* Find connected operacakes */ /* Find connected operacakes */
for (int addr = 0; addr < 8; addr++) { for (int addr = 0; addr < 8; addr++) {
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_OUTPUT, operacake_write_reg(
OPERACAKE_DEFAULT_OUTPUT); oc_bus,
operacake_write_reg(oc_bus, addr, OPERACAKE_REG_CONFIG, addr,
OPERACAKE_CONFIG_ALL_OUTPUT); 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); uint8_t reg = operacake_read_reg(oc_bus, addr, OPERACAKE_REG_CONFIG);
operacake_boards[addr].present = (reg == OPERACAKE_CONFIG_ALL_OUTPUT); operacake_boards[addr].present = (reg == OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_boards[addr].mode = MODE_MANUAL; operacake_boards[addr].mode = MODE_MANUAL;
operacake_boards[addr].PA = OPERACAKE_PORT_A1; operacake_boards[addr].PA = OPERACAKE_PORT_A1;
operacake_boards[addr].PB = OPERACAKE_PORT_B1; operacake_boards[addr].PB = OPERACAKE_PORT_B1;
} }
allow_gpio_mode = allow_gpio; allow_gpio_mode = allow_gpio;
if (allow_gpio) { if (allow_gpio) {
@ -136,14 +145,16 @@ uint8_t operacake_init(bool allow_gpio) {
return 0; return 0;
} }
bool operacake_is_board_present(uint8_t address) { bool operacake_is_board_present(uint8_t address)
{
if (address >= OPERACAKE_MAX_BOARDS) if (address >= OPERACAKE_MAX_BOARDS)
return false; return false;
return operacake_boards[address].present; return operacake_boards[address].present;
} }
void operacake_get_boards(uint8_t *addresses) { void operacake_get_boards(uint8_t* addresses)
{
int count = 0; int count = 0;
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) { for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
addresses[i] = OPERACAKE_ADDRESS_INVALID; addresses[i] = OPERACAKE_ADDRESS_INVALID;
@ -154,25 +165,26 @@ void operacake_get_boards(uint8_t *addresses) {
} }
} }
uint8_t port_to_pins(uint8_t port) { uint8_t port_to_pins(uint8_t port)
switch(port) { {
case OPERACAKE_PA1: switch (port) {
return OPERACAKE_PORT_A1; case OPERACAKE_PA1:
case OPERACAKE_PA2: return OPERACAKE_PORT_A1;
return OPERACAKE_PORT_A2; case OPERACAKE_PA2:
case OPERACAKE_PA3: return OPERACAKE_PORT_A2;
return OPERACAKE_PORT_A3; case OPERACAKE_PA3:
case OPERACAKE_PA4: return OPERACAKE_PORT_A3;
return OPERACAKE_PORT_A4; case OPERACAKE_PA4:
return OPERACAKE_PORT_A4;
case OPERACAKE_PB1: case OPERACAKE_PB1:
return OPERACAKE_PORT_B1; return OPERACAKE_PORT_B1;
case OPERACAKE_PB2: case OPERACAKE_PB2:
return OPERACAKE_PORT_B2; return OPERACAKE_PORT_B2;
case OPERACAKE_PB3: case OPERACAKE_PB3:
return OPERACAKE_PORT_B3; return OPERACAKE_PORT_B3;
case OPERACAKE_PB4: case OPERACAKE_PB4:
return OPERACAKE_PORT_B4; return OPERACAKE_PORT_B4;
} }
return 0xFF; return 0xFF;
} }
@ -188,8 +200,8 @@ uint8_t operacake_activate_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 1; return 1;
} }
/* Ensure PA and PB are on opposite sides. */ /* Ensure PA and PB are on opposite sides. */
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) ||
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) { ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
return 1; return 1;
} }
@ -207,7 +219,8 @@ uint8_t operacake_activate_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 0; return 0;
} }
void operacake_set_mode(uint8_t address, uint8_t mode) { void operacake_set_mode(uint8_t address, uint8_t mode)
{
if (address >= OPERACAKE_MAX_BOARDS) if (address >= OPERACAKE_MAX_BOARDS)
return; return;
@ -216,12 +229,25 @@ void operacake_set_mode(uint8_t address, uint8_t mode) {
if (mode == MODE_TIME) { if (mode == MODE_TIME) {
// Switch Opera Cake to pin-control mode // Switch Opera Cake to pin-control mode
uint8_t config_pins = (uint8_t)~(OPERACAKE_PIN_OE(1) | OPERACAKE_PIN_LEDEN(1) | OPERACAKE_PIN_LEDEN2(1)); uint8_t config_pins = (uint8_t) ~(
OPERACAKE_PIN_OE(1) | OPERACAKE_PIN_LEDEN(1) |
OPERACAKE_PIN_LEDEN2(1));
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, config_pins); operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, config_pins);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS); operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_OUTPUT,
OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS);
} else { } else {
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, OPERACAKE_CONFIG_ALL_OUTPUT); operacake_write_reg(
operacake_activate_ports(address, operacake_boards[address].PA, operacake_boards[address].PB); oc_bus,
address,
OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_activate_ports(
address,
operacake_boards[address].PA,
operacake_boards[address].PB);
} }
// If any boards are in MODE_TIME, enable the sctimer events. // If any boards are in MODE_TIME, enable the sctimer events.
@ -233,7 +259,8 @@ void operacake_set_mode(uint8_t address, uint8_t mode) {
operacake_sctimer_enable(enable_sctimer); operacake_sctimer_enable(enable_sctimer);
} }
uint8_t operacake_get_mode(uint8_t address) { uint8_t operacake_get_mode(uint8_t address)
{
if (address >= OPERACAKE_MAX_BOARDS) if (address >= OPERACAKE_MAX_BOARDS)
return 0; return 0;
@ -250,8 +277,8 @@ uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB)
return 1; return 1;
} }
/* Ensure PA and PB are on opposite sides. */ /* Ensure PA and PB are on opposite sides. */
if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) if (((PA <= OPERACAKE_PA4) && (PB <= OPERACAKE_PA4)) ||
|| ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) { ((PA > OPERACAKE_PA4) && (PB > OPERACAKE_PA4))) {
return 1; return 1;
} }
@ -280,8 +307,9 @@ typedef struct {
static operacake_range ranges[MAX_OPERACAKE_RANGES * sizeof(operacake_range)]; static operacake_range ranges[MAX_OPERACAKE_RANGES * sizeof(operacake_range)];
static uint8_t range_idx = 0; static uint8_t range_idx = 0;
uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port) { uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port)
if(range_idx >= MAX_OPERACAKE_RANGES) { {
if (range_idx >= MAX_OPERACAKE_RANGES) {
return 1; return 1;
} }
ranges[range_idx].freq_min = freq_min; ranges[range_idx].freq_min = freq_min;
@ -296,20 +324,21 @@ uint8_t operacake_add_range(uint16_t freq_min, uint16_t freq_max, uint8_t port)
void operacake_clear_ranges(void) void operacake_clear_ranges(void)
{ {
range_idx = 0; range_idx = 0;
} }
#define FREQ_ONE_MHZ (1000000ull) #define FREQ_ONE_MHZ (1000000ull)
uint8_t operacake_set_range(uint32_t freq_mhz) { uint8_t operacake_set_range(uint32_t freq_mhz)
if(range_idx == 0) { {
if (range_idx == 0) {
return 1; return 1;
} }
int range; int range;
for(range=0; range<range_idx; range++) { for (range = 0; range < range_idx; range++) {
if((freq_mhz >= ranges[range].freq_min) if ((freq_mhz >= ranges[range].freq_min) &&
&& (freq_mhz <= ranges[range].freq_max)) { (freq_mhz <= ranges[range].freq_max)) {
break; break;
} }
} }
@ -317,13 +346,17 @@ uint8_t operacake_set_range(uint32_t freq_mhz) {
if (range == range_idx) { if (range == range_idx) {
range--; range--;
} }
if(range == current_range) { if (range == current_range) {
return 1; return 1;
} }
for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) { for (int i = 0; i < OPERACAKE_MAX_BOARDS; i++) {
if (operacake_is_board_present(i) && operacake_get_mode(i) == MODE_FREQUENCY) { if (operacake_is_board_present(i) &&
operacake_activate_ports(i, ranges[range].portA, ranges[range].portB); operacake_get_mode(i) == MODE_FREQUENCY) {
operacake_activate_ports(
i,
ranges[range].portA,
ranges[range].portB);
break; break;
} }
} }
@ -339,7 +372,7 @@ uint16_t gpio_test(uint8_t address)
{ {
uint8_t i, reg, bit_mask, gpio_mask = 0x1F; uint8_t i, reg, bit_mask, gpio_mask = 0x1F;
uint16_t result = 0; uint16_t result = 0;
if(!allow_gpio_mode) if (!allow_gpio_mode)
return 0xFFFF; return 0xFFFF;
scu_pinmux(SCU_PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_PINMUX_GPIO3_8, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
@ -358,17 +391,23 @@ uint16_t gpio_test(uint8_t address)
// Setup I2C to put it in GPIO mode // Setup I2C to put it in GPIO mode
reg = (OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS); reg = (OPERACAKE_GPIO_ENABLE | OPERACAKE_EN_LEDS);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, reg); operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, reg);
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, operacake_write_reg(
OPERACAKE_CONFIG_GPIO_INPUTS); oc_bus,
operacake_write_reg(oc_bus, address, OPERACAKE_REG_POLARITY, address,
OPERACAKE_POLARITY_NORMAL); OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_GPIO_INPUTS);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_POLARITY,
OPERACAKE_POLARITY_NORMAL);
// clear state // clear state
for(i=0; i<5; i++) { for (i = 0; i < 5; i++) {
gpio_output(&gpio_pins[i]); gpio_output(&gpio_pins[i]);
gpio_write(&gpio_pins[i], 0); gpio_write(&gpio_pins[i], 0);
} }
// Test each pin separately // Test each pin separately
for(i=0; i<5; i++) { for (i = 0; i < 5; i++) {
// Set pin high // Set pin high
gpio_write(&gpio_pins[i], 1); gpio_write(&gpio_pins[i], 1);
// check input // check input
@ -377,12 +416,12 @@ uint16_t gpio_test(uint8_t address)
reg &= gpio_mask; reg &= gpio_mask;
bit_mask = 1 << i; bit_mask = 1 << i;
result <<= 1; result <<= 1;
if(!(reg & bit_mask)) { if (!(reg & bit_mask)) {
// Is the correct bit set? // Is the correct bit set?
result |= 1; result |= 1;
} }
result <<= 1; result <<= 1;
if(reg & ~bit_mask) { if (reg & ~bit_mask) {
// Are any other bits set? // Are any other bits set?
result |= 1; result |= 1;
} }
@ -394,21 +433,27 @@ uint16_t gpio_test(uint8_t address)
reg >>= 2; reg >>= 2;
reg &= gpio_mask; reg &= gpio_mask;
bit_mask = 1 << i; bit_mask = 1 << i;
if(reg & bit_mask) { if (reg & bit_mask) {
// Is the correct bit clear? // Is the correct bit clear?
result |= 1; result |= 1;
} }
} }
// clean up // clean up
for(i=0; i<5; i++) { for (i = 0; i < 5; i++) {
gpio_input(&gpio_pins[i]); gpio_input(&gpio_pins[i]);
} }
// Put it back in to I2C mode and set default pins // Put it back in to I2C mode and set default pins
operacake_write_reg(oc_bus, address, OPERACAKE_REG_CONFIG, operacake_write_reg(
OPERACAKE_CONFIG_ALL_OUTPUT); oc_bus,
operacake_write_reg(oc_bus, address, OPERACAKE_REG_OUTPUT, address,
OPERACAKE_DEFAULT_OUTPUT); OPERACAKE_REG_CONFIG,
OPERACAKE_CONFIG_ALL_OUTPUT);
operacake_write_reg(
oc_bus,
address,
OPERACAKE_REG_OUTPUT,
OPERACAKE_DEFAULT_OUTPUT);
return result; return result;
} }

View File

@ -23,8 +23,7 @@
#define __OPERACAKE_H #define __OPERACAKE_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -44,7 +43,7 @@ extern "C"
uint8_t operacake_init(bool allow_gpio); uint8_t operacake_init(bool allow_gpio);
bool operacake_is_board_present(uint8_t address); 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); void operacake_set_mode(uint8_t address, uint8_t mode);
uint8_t operacake_get_mode(uint8_t address); uint8_t operacake_get_mode(uint8_t address);
uint8_t operacake_set_ports(uint8_t address, uint8_t PA, uint8_t PB); 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 <libopencm3/lpc43xx/gima.h>
#include "sct.h" #include "sct.h"
#define U1CTRL_SET SCT_OUT14_SET
#define U1CTRL_SET SCT_OUT14_SET #define U1CTRL_CLR SCT_OUT14_CLR
#define U1CTRL_CLR SCT_OUT14_CLR
#define U2CTRL0_SET SCT_OUT13_SET #define U2CTRL0_SET SCT_OUT13_SET
#define U2CTRL0_CLR SCT_OUT13_CLR #define U2CTRL0_CLR SCT_OUT13_CLR
#define U2CTRL1_SET SCT_OUT12_SET #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 * To trigger the antenna switching synchronously with the sample clock, the
* SGPIO is configured to output its clock (f=2 * sample clock) to the SCTimer. * SGPIO is configured to output its clock (f=2 * sample clock) to the SCTimer.
*/ */
void operacake_sctimer_init() { void operacake_sctimer_init()
{
// We start by resetting the SCTimer // We start by resetting the SCTimer
RESET_CTRL1 = RESET_CTRL1_SCT_RST; RESET_CTRL1 = RESET_CTRL1_SCT_RST;
@ -67,33 +67,39 @@ void operacake_sctimer_init() {
// this delay may need to be increased. // this delay may need to be increased.
delay(8); delay(8);
// Pin definitions for the HackRF // Pin definitions for the HackRF
// U2CTRL0 // U2CTRL0
scu_pinmux(P7_4, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_4,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U2CTRL1 // U2CTRL1
scu_pinmux(P7_5, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_5,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U3CTRL0 // U3CTRL0
scu_pinmux(P7_6, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_6,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U3CTRL1 // U3CTRL1
scu_pinmux(P7_7, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_7,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// U1CTRL // U1CTRL
scu_pinmux(P7_0, SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1); scu_pinmux(
P7_0,
SCU_CONF_EPUN_DIS_PULLUP | SCU_CONF_EHS_FAST | SCU_CONF_FUNCTION1);
// Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12 // Configure the SGPIO to output the clock (f=2 * sample clock) on pin 12
SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG12 = SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode
SGPIO_OUT_MUX_CFG_P_OUT_CFG(0x08) | // clkout output mode SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe
SGPIO_OUT_MUX_CFG_P_OE_CFG(0); // gpio_oe
SGPIO_GPIO_OENREG |= BIT12; SGPIO_GPIO_OENREG |= BIT12;
// Use the GIMA to connect the SGPIO clock to the SCTimer // 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 // We configure this register first, because the user manual says to
SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT SCT_CONFIG |= SCT_CONFIG_UNIFY_32_BIT | SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK |
| SCT_CONFIG_CLKMODE_PRESCALED_BUS_CLOCK SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1;
| SCT_CONFIG_CKSEL_RISING_EDGES_ON_INPUT_1;
// Halt the SCTimer to enable it to be configured // Halt the SCTimer to enable it to be configured
SCT_CTRL = SCT_CTRL_HALT_L(1); SCT_CTRL = SCT_CTRL_HALT_L(1);
@ -108,32 +114,34 @@ void operacake_sctimer_init() {
SCT_CTRL &= ~SCT_CTRL_HALT_L(1); SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
} }
static uint32_t operacake_sctimer_port_to_output(uint8_t port) { static uint32_t operacake_sctimer_port_to_output(uint8_t port)
{
int bit0 = (port >> 0) & 1; int bit0 = (port >> 0) & 1;
int bit1 = (port >> 1) & 1; int bit1 = (port >> 1) & 1;
int bit2 = (port >> 2) & 1; int bit2 = (port >> 2) & 1;
return (bit0 << 11) | (bit0 << 13) | return (bit0 << 11) | (bit0 << 13) | (bit1 << 8) | (bit1 << 12) |
(bit1 << 8) | (bit1 << 12) | (((~bit2) & 1) << 14);
(((~bit2)&1) << 14);
} }
void operacake_sctimer_enable(bool enable) { void operacake_sctimer_enable(bool enable)
{
SCT_CTRL = SCT_CTRL_HALT_L(1); SCT_CTRL = SCT_CTRL_HALT_L(1);
SCT_STATE = enable; SCT_STATE = enable;
SCT_CTRL &= ~SCT_CTRL_HALT_L(1); SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
} }
void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int n) { void operacake_sctimer_set_dwell_times(struct operacake_dwell_times* times, int n)
{
SCT_CTRL = SCT_CTRL_HALT_L(1); SCT_CTRL = SCT_CTRL_HALT_L(1);
uint32_t counter = 0; uint32_t counter = 0;
uint32_t bit0_set = 0, bit0_clr = 0, bit1_set = 0, bit1_clr = 0, bit2_set = 0, bit2_clr = 0; uint32_t bit0_set = 0, bit0_clr = 0, bit1_set = 0, bit1_clr = 0, bit2_set = 0,
bit2_clr = 0;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
// Enable event i in state 1, set to match on match register i // Enable event i in state 1, set to match on match register i
SCT_EVn_STATE(i) = SCT_EVn_STATE_STATEMSK1(1); SCT_EVn_STATE(i) = SCT_EVn_STATE_STATEMSK1(1);
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 // Calculate the counter value to match on
counter += times[i].dwell; counter += times[i].dwell;
@ -143,7 +151,7 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
if (i == 0) if (i == 0)
counter -= 1; counter -= 1;
SCT_MATCHn(i) = counter; SCT_MATCHn(i) = counter;
SCT_MATCHRELn(i) = counter; SCT_MATCHRELn(i) = counter;
// The match event selects the *next* port, so retreive that here. // The match event selects the *next* port, so retreive that here.
@ -151,7 +159,7 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
if (i == n - 1) { if (i == n - 1) {
port = times[0].port; port = times[0].port;
} else { } else {
port = times[i+1].port; port = times[i + 1].port;
} }
int bit0 = (port >> 0) & 1; int bit0 = (port >> 0) & 1;
@ -159,15 +167,15 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
int bit2 = (port >> 2) & 1; int bit2 = (port >> 2) & 1;
// Find bits to set/clear on event i // 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); 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); bit1_clr |= SCT_OUTn_CLRm(~bit1, i);
// (U1CTRL is inverted) // (U1CTRL is inverted)
bit2_set |= SCT_OUTn_SETm(~bit2, i); 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 // Apply event set/clear mappings
@ -179,20 +187,21 @@ void operacake_sctimer_set_dwell_times(struct operacake_dwell_times *times, int
U2CTRL1_CLR = bit1_clr; U2CTRL1_CLR = bit1_clr;
U3CTRL1_SET = bit1_set; U3CTRL1_SET = bit1_set;
U3CTRL1_CLR = bit1_clr; U3CTRL1_CLR = bit1_clr;
U1CTRL_SET = bit2_set; U1CTRL_SET = bit2_set;
U1CTRL_CLR = bit2_clr; U1CTRL_CLR = bit2_clr;
// Set output pins to select the first port in the list // Set output pins to select the first port in the list
default_output = operacake_sctimer_port_to_output(times[0].port); default_output = operacake_sctimer_port_to_output(times[0].port);
SCT_OUTPUT = default_output; SCT_OUTPUT = default_output;
// Reset counter on final event // Reset counter on final event
SCT_LIMIT = (1 << (n-1)); SCT_LIMIT = (1 << (n - 1));
SCT_CTRL &= ~SCT_CTRL_HALT_L(1); SCT_CTRL &= ~SCT_CTRL_HALT_L(1);
} }
void operacake_sctimer_stop() { void operacake_sctimer_stop()
{
// Halt timer // Halt timer
SCT_CTRL |= SCT_CTRL_HALT_L(1); SCT_CTRL |= SCT_CTRL_HALT_L(1);
} }
@ -203,7 +212,8 @@ void operacake_sctimer_stop() {
* called by set_transceiver_mode so the HackRF starts capturing with the * called by set_transceiver_mode so the HackRF starts capturing with the
* same antenna selected each time. * same antenna selected each time.
*/ */
void operacake_sctimer_reset_state() { void operacake_sctimer_reset_state()
{
SCT_CTRL |= SCT_CTRL_HALT_L(1); SCT_CTRL |= SCT_CTRL_HALT_L(1);
// Clear the counter value // Clear the counter value

View File

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

View File

@ -26,9 +26,10 @@
#include <libopencm3/lpc43xx/scu.h> #include <libopencm3/lpc43xx/scu.h>
static void portapack_sleep_milliseconds(const uint32_t milliseconds) { static void portapack_sleep_milliseconds(const uint32_t milliseconds)
{
/* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */ /* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */
delay(milliseconds * 40800); delay(milliseconds * 40800);
} }
// clang-format off // clang-format off
@ -41,6 +42,7 @@ static struct gpio_t gpio_unused = GPIO(5, 7); /* P2_8 */
static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */ static struct gpio_t gpio_lcd_rdx = GPIO(5, 4); /* P2_4 */
static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */ static struct gpio_t gpio_lcd_wrx = GPIO(1, 10); /* P2_9 */
static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */ static struct gpio_t gpio_dir = GPIO(1, 13); /* P2_13 */
// clang-format on // clang-format on
typedef struct portapack_if_t { typedef struct portapack_if_t {
@ -54,39 +56,44 @@ typedef struct portapack_if_t {
} portapack_if_t; } portapack_if_t;
static portapack_if_t portapack_if = { static portapack_if_t portapack_if = {
.gpio_dir = &gpio_dir, .gpio_dir = &gpio_dir,
.gpio_lcd_rdx = &gpio_lcd_rdx, .gpio_lcd_rdx = &gpio_lcd_rdx,
.gpio_lcd_wrx = &gpio_lcd_wrx, .gpio_lcd_wrx = &gpio_lcd_wrx,
.gpio_io_stbx = &gpio_io_stbx, .gpio_io_stbx = &gpio_io_stbx,
.gpio_addr = &gpio_addr, .gpio_addr = &gpio_addr,
.gpio_port_data = GPIO_LPC_PORT(3), .gpio_port_data = GPIO_LPC_PORT(3),
.io_reg = 0x03, .io_reg = 0x03,
}; };
/* NOTE: Code below assumes the shift value is "8". */ /* NOTE: Code below assumes the shift value is "8". */
#define GPIO_DATA_SHIFT (8) #define GPIO_DATA_SHIFT (8)
static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT; static const uint32_t gpio_data_mask = 0xFFU << GPIO_DATA_SHIFT;
static void portapack_data_mask_set() { static void portapack_data_mask_set()
{
portapack_if.gpio_port_data->mask = ~gpio_data_mask; portapack_if.gpio_port_data->mask = ~gpio_data_mask;
} }
static void portapack_data_write_low(const uint32_t value) { static void portapack_data_write_low(const uint32_t value)
{
portapack_if.gpio_port_data->mpin = (value << GPIO_DATA_SHIFT); portapack_if.gpio_port_data->mpin = (value << GPIO_DATA_SHIFT);
} }
static void portapack_data_write_high(const uint32_t value) { static void portapack_data_write_high(const uint32_t value)
{
/* NOTE: Assumes no other bits in the port are masked. */ /* NOTE: Assumes no other bits in the port are masked. */
/* NOTE: Assumes that bits 15 through 8 are masked. */ /* NOTE: Assumes that bits 15 through 8 are masked. */
portapack_if.gpio_port_data->mpin = value; portapack_if.gpio_port_data->mpin = value;
} }
static void portapack_dir_read() { static void portapack_dir_read()
{
portapack_if.gpio_port_data->dir &= ~gpio_data_mask; portapack_if.gpio_port_data->dir &= ~gpio_data_mask;
gpio_set(portapack_if.gpio_dir); gpio_set(portapack_if.gpio_dir);
} }
static void portapack_dir_write() { static void portapack_dir_write()
{
gpio_clear(portapack_if.gpio_dir); gpio_clear(portapack_if.gpio_dir);
portapack_if.gpio_port_data->dir |= gpio_data_mask; portapack_if.gpio_port_data->dir |= gpio_data_mask;
/* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin /* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin
@ -97,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); gpio_clear(portapack_if.gpio_lcd_rdx);
} }
static void portapack_lcd_rd_deassert() { static void portapack_lcd_rd_deassert()
{
gpio_set(portapack_if.gpio_lcd_rdx); gpio_set(portapack_if.gpio_lcd_rdx);
} }
static void portapack_lcd_wr_assert() { static void portapack_lcd_wr_assert()
{
gpio_clear(portapack_if.gpio_lcd_wrx); gpio_clear(portapack_if.gpio_lcd_wrx);
} }
static void portapack_lcd_wr_deassert() { static void portapack_lcd_wr_deassert()
{
gpio_set(portapack_if.gpio_lcd_wrx); gpio_set(portapack_if.gpio_lcd_wrx);
} }
static void portapack_io_stb_assert() { static void portapack_io_stb_assert()
{
gpio_clear(portapack_if.gpio_io_stbx); gpio_clear(portapack_if.gpio_io_stbx);
} }
static void portapack_io_stb_deassert() { static void portapack_io_stb_deassert()
{
gpio_set(portapack_if.gpio_io_stbx); gpio_set(portapack_if.gpio_io_stbx);
} }
static void portapack_addr(const bool value) { static void portapack_addr(const bool value)
{
gpio_write(portapack_if.gpio_addr, value); gpio_write(portapack_if.gpio_addr, value);
} }
static void portapack_lcd_command(const uint32_t value) { static void portapack_lcd_command(const uint32_t value)
portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */ {
portapack_dir_write(); /* Turn around data bus, MCU->CPLD */ portapack_data_write_high(0); /* Drive high byte (with zero -- don't care) */
portapack_addr(0); /* Indicate command */ portapack_dir_write(); /* Turn around data bus, MCU->CPLD */
portapack_addr(0); /* Indicate command */
__asm__("nop"); __asm__("nop");
__asm__("nop"); __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"); __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. // NOTE: Assumes and DIR=0 and ADDR=1 from command phase.
portapack_data_write_high(value); /* Drive high byte */ portapack_data_write_high(value); /* Drive high byte */
__asm__("nop"); __asm__("nop");
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"); __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_data_write_low(value);
portapack_dir_write(); portapack_dir_write();
portapack_addr(address); portapack_addr(address);
@ -170,7 +187,8 @@ static void portapack_io_write(const bool address, const uint_fast16_t value) {
portapack_io_stb_deassert(); portapack_io_stb_deassert();
} }
static void portapack_if_init() { static void portapack_if_init()
{
portapack_data_mask_set(); portapack_data_mask_set();
portapack_data_write_high(0); portapack_data_write_high(0);
@ -197,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_D6, SCU_CONF_FUNCTION0 | SCU_GPIO_PDN);
scu_pinmux(SCU_PINMUX_PP_D7, 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_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_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_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_LCD_TE, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */
/* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */ /* scu_pinmux(SCU_PINMUX_PP_UNUSED, SCU_CONF_FUNCTION4 | SCU_GPIO_NOPULL); */
} }
static void portapack_lcd_reset_state(const bool active) { static void portapack_lcd_reset_state(const bool active)
{
portapack_if.io_reg = (portapack_if.io_reg & 0xfe) | (active ? (1 << 0) : 0); portapack_if.io_reg = (portapack_if.io_reg & 0xfe) | (active ? (1 << 0) : 0);
portapack_io_write(1, portapack_if.io_reg); portapack_io_write(1, portapack_if.io_reg);
} }
@ -214,15 +233,16 @@ static void portapack_lcd_reset_state(const bool active) {
static void portapack_lcd_data_write_command_and_data( static void portapack_lcd_data_write_command_and_data(
const uint_fast8_t command, const uint_fast8_t command,
const uint8_t* data, const uint8_t* data,
const size_t data_count const size_t data_count)
) { {
portapack_lcd_command(command); portapack_lcd_command(command);
for(size_t i=0; i<data_count; i++) { for (size_t i = 0; i < data_count; i++) {
portapack_lcd_write_data(data[i]); portapack_lcd_write_data(data[i]);
} }
} }
static void portapack_lcd_sleep_out() { static void portapack_lcd_sleep_out()
{
const uint8_t cmd_11[] = {}; const uint8_t cmd_11[] = {};
portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11)); portapack_lcd_data_write_command_and_data(0x11, cmd_11, ARRAY_SIZEOF(cmd_11));
// "It will be necessary to wait 120msec after sending Sleep Out // "It will be necessary to wait 120msec after sending Sleep Out
@ -231,56 +251,68 @@ static void portapack_lcd_sleep_out() {
portapack_sleep_milliseconds(120); portapack_sleep_milliseconds(120);
} }
static void portapack_lcd_display_on() { static void portapack_lcd_display_on()
{
const uint8_t cmd_29[] = {}; const uint8_t cmd_29[] = {};
portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29)); portapack_lcd_data_write_command_and_data(0x29, cmd_29, ARRAY_SIZEOF(cmd_29));
} }
static void portapack_lcd_ramwr_start() { static void portapack_lcd_ramwr_start()
{
const uint8_t cmd_2c[] = {}; const uint8_t cmd_2c[] = {};
portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c)); portapack_lcd_data_write_command_and_data(0x2c, cmd_2c, ARRAY_SIZEOF(cmd_2c));
} }
static void portapack_lcd_set(const uint_fast8_t command, const uint_fast16_t start, const uint_fast16_t end) { static void portapack_lcd_set(
const uint8_t data[] = { const uint_fast8_t command,
(start >> 8), (start & 0xff), const uint_fast16_t start,
(end >> 8), (end & 0xff) const uint_fast16_t end)
}; {
const uint8_t data[] = {(start >> 8), (start & 0xff), (end >> 8), (end & 0xff)};
portapack_lcd_data_write_command_and_data(command, data, ARRAY_SIZEOF(data)); portapack_lcd_data_write_command_and_data(command, data, ARRAY_SIZEOF(data));
} }
static void portapack_lcd_caset(const uint_fast16_t start_column, const uint_fast16_t end_column) { static void portapack_lcd_caset(
const uint_fast16_t start_column,
const uint_fast16_t end_column)
{
portapack_lcd_set(0x2a, start_column, end_column); portapack_lcd_set(0x2a, start_column, end_column);
} }
static void portapack_lcd_paset(const uint_fast16_t start_page, const uint_fast16_t end_page) { static void portapack_lcd_paset(
const uint_fast16_t start_page,
const uint_fast16_t end_page)
{
portapack_lcd_set(0x2b, start_page, end_page); portapack_lcd_set(0x2b, start_page, end_page);
} }
static void portapack_lcd_start_ram_write( static void portapack_lcd_start_ram_write(const ui_rect_t rect)
const ui_rect_t rect {
) { portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1);
portapack_lcd_caset(rect.point.x, rect.point.x + rect.size.width - 1);
portapack_lcd_paset(rect.point.y, rect.point.y + rect.size.height - 1); portapack_lcd_paset(rect.point.y, rect.point.y + rect.size.height - 1);
portapack_lcd_ramwr_start(); portapack_lcd_ramwr_start();
} }
static void portapack_lcd_write_pixel(const ui_color_t pixel) { static void portapack_lcd_write_pixel(const ui_color_t pixel)
{
portapack_lcd_write_data(pixel.v); portapack_lcd_write_data(pixel.v);
} }
static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n) { static void portapack_lcd_write_pixels_color(const ui_color_t c, size_t n)
while(n--) { {
while (n--) {
portapack_lcd_write_data(c.v); portapack_lcd_write_data(c.v);
} }
} }
static void portapack_lcd_wake() { static void portapack_lcd_wake()
{
portapack_lcd_sleep_out(); portapack_lcd_sleep_out();
portapack_lcd_display_on(); portapack_lcd_display_on();
} }
static void portapack_lcd_reset() { static void portapack_lcd_reset()
{
portapack_lcd_reset_state(false); portapack_lcd_reset_state(false);
portapack_sleep_milliseconds(1); portapack_sleep_milliseconds(1);
portapack_lcd_reset_state(true); portapack_lcd_reset_state(true);
@ -289,7 +321,8 @@ static void portapack_lcd_reset() {
portapack_sleep_milliseconds(120); portapack_sleep_milliseconds(120);
} }
static void portapack_lcd_init() { static void portapack_lcd_init()
{
// LCDs are configured for IM[2:0] = 001 // LCDs are configured for IM[2:0] = 001
// 8080-I system, 16-bit parallel bus // 8080-I system, 16-bit parallel bus
@ -300,30 +333,30 @@ static void portapack_lcd_init() {
// Power control B // Power control B
// 0 // 0
// PCEQ=1, DRV_ena=0, Power control=3 // 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)); portapack_lcd_data_write_command_and_data(0xCF, cmd_cf, ARRAY_SIZEOF(cmd_cf));
// Power on sequence control // 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)); portapack_lcd_data_write_command_and_data(0xED, cmd_ed, ARRAY_SIZEOF(cmd_ed));
// Driver timing control A // 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)); portapack_lcd_data_write_command_and_data(0xE8, cmd_e8, ARRAY_SIZEOF(cmd_e8));
// Power control A // 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)); portapack_lcd_data_write_command_and_data(0xCB, cmd_cb, ARRAY_SIZEOF(cmd_cb));
// Pump ratio control // 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)); portapack_lcd_data_write_command_and_data(0xF7, cmd_f7, ARRAY_SIZEOF(cmd_f7));
// Driver timing control B // 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)); 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)); portapack_lcd_data_write_command_and_data(0xB1, cmd_b1, ARRAY_SIZEOF(cmd_b1));
// Blanking Porch Control // Blanking Porch Control
@ -331,7 +364,7 @@ static void portapack_lcd_init() {
// VBP = 0b0000010 = 2 (number of HSYNC of vertical back porch) // VBP = 0b0000010 = 2 (number of HSYNC of vertical back porch)
// HFP = 0b0001010 = 10 (number of DOTCLOCK of horizontal front porch) // HFP = 0b0001010 = 10 (number of DOTCLOCK of horizontal front porch)
// HBP = 0b0010100 = 20 (number of DOTCLOCK of horizontal back 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)); portapack_lcd_data_write_command_and_data(0xB5, cmd_b5, ARRAY_SIZEOF(cmd_b5));
// Display Function Control // Display Function Control
@ -344,42 +377,42 @@ static void portapack_lcd_init() {
// REV = 1 (normally white) // REV = 1 (normally white)
// NL = 0b100111 (default) // NL = 0b100111 (default)
// PCDIV = 0b000000 (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)); portapack_lcd_data_write_command_and_data(0xB6, cmd_b6, ARRAY_SIZEOF(cmd_b6));
// Power Control 1 // Power Control 1
//VRH[5:0] //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)); portapack_lcd_data_write_command_and_data(0xC0, cmd_c0, ARRAY_SIZEOF(cmd_c0));
// Power Control 2 // Power Control 2
//SAP[2:0];BT[3:0] //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)); portapack_lcd_data_write_command_and_data(0xC1, cmd_c1, ARRAY_SIZEOF(cmd_c1));
// VCOM Control 1 // 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)); portapack_lcd_data_write_command_and_data(0xC5, cmd_c5, ARRAY_SIZEOF(cmd_c5));
// VCOM Control 2 // 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)); portapack_lcd_data_write_command_and_data(0xC7, cmd_c7, ARRAY_SIZEOF(cmd_c7));
// Memory Access Control // Memory Access Control
// Invert X and Y memory access order, so upper-left of // Invert X and Y memory access order, so upper-left of
// screen is (0,0) when writing to display. // screen is (0,0) when writing to display.
const uint8_t cmd_36[] = { const uint8_t cmd_36[] = {
(1 << 7) | // MY=1 (1 << 7) | // MY=1
(1 << 6) | // MX=1 (1 << 6) | // MX=1
(0 << 5) | // MV=0 (0 << 5) | // MV=0
(1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic (1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic
(1 << 3) // BGR=1: For Kingtech LCD, BGR filter. (1 << 3) // BGR=1: For Kingtech LCD, BGR filter.
}; };
portapack_lcd_data_write_command_and_data(0x36, cmd_36, ARRAY_SIZEOF(cmd_36)); portapack_lcd_data_write_command_and_data(0x36, cmd_36, ARRAY_SIZEOF(cmd_36));
// COLMOD: Pixel Format Set // COLMOD: Pixel Format Set
// DPI=101 (16 bits/pixel), DBI=101 (16 bits/pixel) // 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(0x3A, cmd_3a, ARRAY_SIZEOF(cmd_3a));
//portapack_lcd_data_write_command_and_data(0xF6, { 0x01, 0x30 }); //portapack_lcd_data_write_command_and_data(0xF6, { 0x01, 0x30 });
@ -390,59 +423,84 @@ static void portapack_lcd_init() {
// RM=0 (system interface/VSYNC interface) // RM=0 (system interface/VSYNC interface)
// DM[1:0]=00 (internal clock operation) // DM[1:0]=00 (internal clock operation)
// ENDIAN=0 (doesn't matter with 16-bit interface) // 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)); portapack_lcd_data_write_command_and_data(0xF6, cmd_f6, ARRAY_SIZEOF(cmd_f6));
// 3Gamma Function Disable // 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)); portapack_lcd_data_write_command_and_data(0xF2, cmd_f2, ARRAY_SIZEOF(cmd_f2));
// Gamma curve selected // 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)); portapack_lcd_data_write_command_and_data(0x26, cmd_26, ARRAY_SIZEOF(cmd_26));
// Set Gamma // Set Gamma
const uint8_t cmd_e0[] = { const uint8_t cmd_e0[] = {
0x0F, 0x1D, 0x19, 0x0E, 0x10, 0x07, 0x4C, 0x63, 0x0F,
0x3F, 0x03, 0x0D, 0x00, 0x26, 0x24, 0x04 0x1D,
}; 0x19,
0x0E,
0x10,
0x07,
0x4C,
0x63,
0x3F,
0x03,
0x0D,
0x00,
0x26,
0x24,
0x04};
portapack_lcd_data_write_command_and_data(0xE0, cmd_e0, ARRAY_SIZEOF(cmd_e0)); portapack_lcd_data_write_command_and_data(0xE0, cmd_e0, ARRAY_SIZEOF(cmd_e0));
// Set Gamma // Set Gamma
const uint8_t cmd_e1[] = { const uint8_t cmd_e1[] = {
0x00, 0x1C, 0x1F, 0x02, 0x0F, 0x03, 0x35, 0x25, 0x00,
0x47, 0x04, 0x0C, 0x0B, 0x29, 0x2F, 0x05 0x1C,
}; 0x1F,
0x02,
0x0F,
0x03,
0x35,
0x25,
0x47,
0x04,
0x0C,
0x0B,
0x29,
0x2F,
0x05};
portapack_lcd_data_write_command_and_data(0xE1, cmd_e1, ARRAY_SIZEOF(cmd_e1)); portapack_lcd_data_write_command_and_data(0xE1, cmd_e1, ARRAY_SIZEOF(cmd_e1));
portapack_lcd_wake(); portapack_lcd_wake();
// Turn on Tearing Effect Line (TE) output signal. // 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)); portapack_lcd_data_write_command_and_data(0x35, cmd_35, ARRAY_SIZEOF(cmd_35));
} }
void portapack_backlight(const bool on) { void portapack_backlight(const bool on)
{
portapack_if.io_reg = (portapack_if.io_reg & 0x7f) | (on ? (1 << 7) : 0); portapack_if.io_reg = (portapack_if.io_reg & 0x7f) | (on ? (1 << 7) : 0);
portapack_io_write(1, portapack_if.io_reg); portapack_io_write(1, portapack_if.io_reg);
} }
void portapack_reference_oscillator(const bool on) { void portapack_reference_oscillator(const bool on)
{
const uint8_t mask = 1 << 6; const uint8_t mask = 1 << 6;
portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0); portapack_if.io_reg = (portapack_if.io_reg & ~mask) | (on ? mask : 0);
portapack_io_write(1, portapack_if.io_reg); portapack_io_write(1, portapack_if.io_reg);
} }
void portapack_fill_rectangle( void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color)
const ui_rect_t rect, {
const ui_color_t color
) {
portapack_lcd_start_ram_write(rect); portapack_lcd_start_ram_write(rect);
portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height); portapack_lcd_write_pixels_color(color, rect.size.width * rect.size.height);
} }
void portapack_clear_display(const ui_color_t color) { void portapack_clear_display(const ui_color_t color)
const ui_rect_t rect_screen = { { 0, 0 }, { 240, 320 } }; {
const ui_rect_t rect_screen = {{0, 0}, {240, 320}};
portapack_fill_rectangle(rect_screen, color); portapack_fill_rectangle(rect_screen, color);
} }
@ -450,33 +508,27 @@ void portapack_draw_bitmap(
const ui_point_t point, const ui_point_t point,
const ui_bitmap_t bitmap, const ui_bitmap_t bitmap,
const ui_color_t foreground, const ui_color_t foreground,
const ui_color_t background const ui_color_t background)
) { {
const ui_rect_t rect = { const ui_rect_t rect = {.point = point, .size = bitmap.size};
.point = point,
.size = bitmap.size
};
portapack_lcd_start_ram_write(rect); portapack_lcd_start_ram_write(rect);
const size_t count = bitmap.size.width * bitmap.size.height; 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)); const uint8_t pixel = bitmap.data[i >> 3] & (1U << (i & 0x7));
portapack_lcd_write_pixel(pixel ? foreground : background); portapack_lcd_write_pixel(pixel ? foreground : background);
} }
} }
ui_bitmap_t portapack_font_glyph( ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c)
const ui_font_t* const font, {
const char c if (c >= font->c_start) {
) {
if( c >= font->c_start ) {
const uint_fast8_t index = c - font->c_start; const uint_fast8_t index = c - font->c_start;
if( index < font->c_count ) { if (index < font->c_count) {
const ui_bitmap_t bitmap = { const ui_bitmap_t bitmap = {
.size = font->glyph_size, .size = font->glyph_size,
.data = &font->data[index * font->data_stride] .data = &font->data[index * font->data_stride]};
};
return bitmap; return bitmap;
} }
} }
@ -488,7 +540,8 @@ ui_bitmap_t portapack_font_glyph(
return bitmap; return bitmap;
} }
static bool jtag_pp_tck(const bool tms_value) { static bool jtag_pp_tck(const bool tms_value)
{
gpio_write(jtag_cpld.gpio->gpio_pp_tms, tms_value); gpio_write(jtag_cpld.gpio->gpio_pp_tms, tms_value);
// 8 ns TMS/TDI to TCK setup // 8 ns TMS/TDI to TCK setup
@ -521,11 +574,12 @@ static bool jtag_pp_tck(const bool tms_value) {
return gpio_read(jtag_cpld.gpio->gpio_pp_tdo); return gpio_read(jtag_cpld.gpio->gpio_pp_tdo);
} }
static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) { static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count)
{
uint32_t result = 0; uint32_t result = 0;
size_t bit_in_index = count - 1; size_t bit_in_index = count - 1;
size_t bit_out_index = 0; size_t bit_out_index = 0;
while(bit_out_index < count) { while (bit_out_index < count) {
const uint32_t tdo = jtag_pp_tck((tms_bits >> bit_in_index) & 1) & 1; const uint32_t tdo = jtag_pp_tck((tms_bits >> bit_in_index) & 1) & 1;
result |= (tdo << bit_out_index); result |= (tdo << bit_out_index);
@ -536,7 +590,8 @@ static uint32_t jtag_pp_shift(const uint32_t tms_bits, const size_t count) {
return result; return result;
} }
static uint32_t jtag_pp_idcode(void) { static uint32_t jtag_pp_idcode(void)
{
cpld_jtag_take(&jtag_cpld); cpld_jtag_take(&jtag_cpld);
/* TODO: Check if PortaPack TMS is floating or driven by an external device. */ /* TODO: Check if PortaPack TMS is floating or driven by an external device. */
@ -556,21 +611,23 @@ static uint32_t jtag_pp_idcode(void) {
return idcode; return idcode;
} }
static bool portapack_detect(void) { static bool portapack_detect(void)
{
return jtag_pp_idcode() == 0x020A50DD; return jtag_pp_idcode() == 0x020A50DD;
} }
static const portapack_t portapack_instance = { static const portapack_t portapack_instance = {};
};
static const portapack_t* portapack_pointer = NULL; static const portapack_t* portapack_pointer = NULL;
const portapack_t* portapack(void) { const portapack_t* portapack(void)
{
return portapack_pointer; return portapack_pointer;
} }
void portapack_init(void) { void portapack_init(void)
if( portapack_detect() ) { {
if (portapack_detect()) {
portapack_if_init(); portapack_if_init();
portapack_lcd_reset(); portapack_lcd_reset();
portapack_lcd_init(); 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_reference_oscillator(const bool on) __attribute__((weak));
void portapack_fill_rectangle( void portapack_fill_rectangle(const ui_rect_t rect, const ui_color_t color);
const ui_rect_t rect,
const ui_color_t color
);
void portapack_clear_display(const ui_color_t color); void portapack_clear_display(const ui_color_t color);
@ -84,12 +81,8 @@ void portapack_draw_bitmap(
const ui_point_t point, const ui_point_t point,
const ui_bitmap_t bitmap, const ui_bitmap_t bitmap,
const ui_color_t foreground, const ui_color_t foreground,
const ui_color_t background const ui_color_t background);
);
ui_bitmap_t portapack_font_glyph( ui_bitmap_t portapack_font_glyph(const ui_font_t* const font, const char c);
const ui_font_t* const font,
const char c
);
#endif/*__PORTAPACK_H__*/ #endif /*__PORTAPACK_H__*/

View File

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

View File

@ -3,6 +3,6 @@
#include <stdint.h> #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 #endif

View File

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

View File

@ -8,14 +8,14 @@
#define RESX 130 #define RESX 130
#define RESY 130 #define RESY 130
#define TYPE_CMD 0 #define TYPE_CMD 0
#define TYPE_DATA 1 #define TYPE_DATA 1
#define _PIN(pin, func, ...) pin #define _PIN(pin, func, ...) pin
#define _FUNC(pin, func, ...) func #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_SCK P1_19, SCU_CONF_FUNCTION1 | SCU_SSP_IO
#define LCD_SSP SSP1_NUM #define LCD_SSP SSP1_NUM
@ -25,6 +25,6 @@ void rad1o_lcdDeInit(void);
void rad1o_lcdFill(uint8_t f); void rad1o_lcdFill(uint8_t f);
void rad1o_lcdDisplay(void); void rad1o_lcdDisplay(void);
void rad1o_lcdSetPixel(uint8_t x, uint8_t y, uint8_t f); void rad1o_lcdSetPixel(uint8_t x, uint8_t y, uint8_t f);
uint8_t *rad1o_lcdGetBuffer(void); uint8_t* rad1o_lcdGetBuffer(void);
#endif #endif

View File

@ -2,11 +2,11 @@
#include <stdint.h> #include <stdint.h>
#define SWAP(p1, p2) \ #define SWAP(p1, p2) \
do { \ do { \
uint8_t SWAP = p1; \ uint8_t SWAP = p1; \
p1 = p2; \ p1 = p2; \
p2 = SWAP; \ p2 = SWAP; \
} while (0) } while (0)
void rad1o_drawHLine(uint8_t y, uint8_t x1, uint8_t x2, uint8_t color) 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; } FONT_CHAR_INFO;
struct FONT_DEF { struct FONT_DEF {
uint8_t u8Width; /* Character width for storage */ uint8_t u8Width; /* Character width for storage */
uint8_t u8Height; /* Character height for storage */ uint8_t u8Height; /* Character height for storage */
uint8_t u8FirstChar; /* The first character available */ uint8_t u8FirstChar; /* The first character available */
uint8_t u8LastChar; /* The last character available */ uint8_t u8LastChar; /* The last character available */
const uint8_t *au8FontTable; /* Font table start address in memory */ const uint8_t* au8FontTable; /* Font table start address in memory */
const FONT_CHAR_INFO *charInfo; /* Pointer to array of char information */ const FONT_CHAR_INFO* charInfo; /* Pointer to array of char information */
const uint16_t *charExtra; /* Pointer to array of extra char info */ const uint16_t* charExtra; /* Pointer to array of extra char info */
}; };
struct EXTFONT { struct EXTFONT {
@ -26,9 +26,9 @@ struct EXTFONT {
struct FONT_DEF def; 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_INTERNAL 1
#define FONT_EXTERNAL 2 #define FONT_EXTERNAL 2

View File

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

View File

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

View File

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

View File

@ -4,8 +4,8 @@
#include "fonts.h" #include "fonts.h"
void rad1o_setTextColor(uint8_t bg, uint8_t fg); 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_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); int rad1o_DoChar(int sx, int sy, int c);
#endif #endif

View File

@ -41,104 +41,104 @@
/* System 7x8 */ /* System 7x8 */
const uint8_t au8Font7x8[] = { const uint8_t au8Font7x8[] = {
0, 0, 0, 0, 0, 0, 0, //' ' 0, 0, 0, 0, 0, 0, 0, //' '
0, 6, 95, 95, 6, 0, 0, //'!' 0, 6, 95, 95, 6, 0, 0, //'!'
0, 7, 7, 0, 7, 7, 0, //'"' 0, 7, 7, 0, 7, 7, 0, //'"'
20, 127, 127, 20, 127, 127, 20, //'#' 20, 127, 127, 20, 127, 127, 20, //'#'
36, 46, 107, 107, 58, 18, 0, //'$' 36, 46, 107, 107, 58, 18, 0, //'$'
70, 102, 48, 24, 12, 102, 98, //'%' 70, 102, 48, 24, 12, 102, 98, //'%'
48, 122, 79, 93, 55, 122, 72, //'&' 48, 122, 79, 93, 55, 122, 72, //'&'
4, 7, 3, 0, 0, 0, 0, //''' 4, 7, 3, 0, 0, 0, 0, //'''
0, 28, 62, 99, 65, 0, 0, //'(' 0, 28, 62, 99, 65, 0, 0, //'('
0, 65, 99, 62, 28, 0, 0, //')' 0, 65, 99, 62, 28, 0, 0, //')'
8, 42, 62, 28, 28, 62, 42, //'*' 8, 42, 62, 28, 28, 62, 42, //'*'
8, 8, 62, 62, 8, 8, 0, //'+' 8, 8, 62, 62, 8, 8, 0, //'+'
0, 128, 224, 96, 0, 0, 0, //',' 0, 128, 224, 96, 0, 0, 0, //','
8, 8, 8, 8, 8, 8, 0, //'-' 8, 8, 8, 8, 8, 8, 0, //'-'
0, 0, 96, 96, 0, 0, 0, //'.' 0, 0, 96, 96, 0, 0, 0, //'.'
96, 48, 24, 12, 6, 3, 1, //'/' 96, 48, 24, 12, 6, 3, 1, //'/'
62, 127, 113, 89, 77, 127, 62, //'0' 62, 127, 113, 89, 77, 127, 62, //'0'
64, 66, 127, 127, 64, 64, 0, //'1' 64, 66, 127, 127, 64, 64, 0, //'1'
98, 115, 89, 73, 111, 102, 0, //'2' 98, 115, 89, 73, 111, 102, 0, //'2'
34, 99, 73, 73, 127, 54, 0, //'3' 34, 99, 73, 73, 127, 54, 0, //'3'
24, 28, 22, 83, 127, 127, 80, //'4' 24, 28, 22, 83, 127, 127, 80, //'4'
39, 103, 69, 69, 125, 57, 0, //'5' 39, 103, 69, 69, 125, 57, 0, //'5'
60, 126, 75, 73, 121, 48, 0, //'6' 60, 126, 75, 73, 121, 48, 0, //'6'
3, 3, 113, 121, 15, 7, 0, //'7' 3, 3, 113, 121, 15, 7, 0, //'7'
54, 127, 73, 73, 127, 54, 0, //'8' 54, 127, 73, 73, 127, 54, 0, //'8'
6, 79, 73, 105, 63, 30, 0, //'9' 6, 79, 73, 105, 63, 30, 0, //'9'
0, 0, 102, 102, 0, 0, 0, //':' 0, 0, 102, 102, 0, 0, 0, //':'
0, 128, 230, 102, 0, 0, 0, //';' 0, 128, 230, 102, 0, 0, 0, //';'
8, 28, 54, 99, 65, 0, 0, //'<' 8, 28, 54, 99, 65, 0, 0, //'<'
36, 36, 36, 36, 36, 36, 0, //'=' 36, 36, 36, 36, 36, 36, 0, //'='
0, 65, 99, 54, 28, 8, 0, //'>' 0, 65, 99, 54, 28, 8, 0, //'>'
2, 3, 81, 89, 15, 6, 0, //'?' 2, 3, 81, 89, 15, 6, 0, //'?'
62, 127, 65, 93, 93, 31, 30, //'@' 62, 127, 65, 93, 93, 31, 30, //'@'
124, 126, 19, 19, 126, 124, 0, //'A' 124, 126, 19, 19, 126, 124, 0, //'A'
65, 127, 127, 73, 73, 127, 54, //'B' 65, 127, 127, 73, 73, 127, 54, //'B'
28, 62, 99, 65, 65, 99, 34, //'C' 28, 62, 99, 65, 65, 99, 34, //'C'
65, 127, 127, 65, 99, 62, 28, //'D' 65, 127, 127, 65, 99, 62, 28, //'D'
65, 127, 127, 73, 93, 65, 99, //'E' 65, 127, 127, 73, 93, 65, 99, //'E'
65, 127, 127, 73, 29, 1, 3, //'F' 65, 127, 127, 73, 29, 1, 3, //'F'
28, 62, 99, 65, 81, 115, 114, //'G' 28, 62, 99, 65, 81, 115, 114, //'G'
127, 127, 8, 8, 127, 127, 0, //'H' 127, 127, 8, 8, 127, 127, 0, //'H'
0, 65, 127, 127, 65, 0, 0, //'I' 0, 65, 127, 127, 65, 0, 0, //'I'
48, 112, 64, 65, 127, 63, 1, //'J' 48, 112, 64, 65, 127, 63, 1, //'J'
65, 127, 127, 8, 28, 119, 99, //'K' 65, 127, 127, 8, 28, 119, 99, //'K'
65, 127, 127, 65, 64, 96, 112, //'L' 65, 127, 127, 65, 64, 96, 112, //'L'
127, 127, 14, 28, 14, 127, 127, //'M' 127, 127, 14, 28, 14, 127, 127, //'M'
127, 127, 6, 12, 24, 127, 127, //'N' 127, 127, 6, 12, 24, 127, 127, //'N'
28, 62, 99, 65, 99, 62, 28, //'O' 28, 62, 99, 65, 99, 62, 28, //'O'
65, 127, 127, 73, 9, 15, 6, //'P' 65, 127, 127, 73, 9, 15, 6, //'P'
30, 63, 33, 113, 127, 94, 0, //'Q' 30, 63, 33, 113, 127, 94, 0, //'Q'
65, 127, 127, 9, 25, 127, 102, //'R' 65, 127, 127, 9, 25, 127, 102, //'R'
38, 111, 77, 89, 115, 50, 0, //'S' 38, 111, 77, 89, 115, 50, 0, //'S'
3, 65, 127, 127, 65, 3, 0, //'T' 3, 65, 127, 127, 65, 3, 0, //'T'
127, 127, 64, 64, 127, 127, 0, //'U' 127, 127, 64, 64, 127, 127, 0, //'U'
31, 63, 96, 96, 63, 31, 0, //'V' 31, 63, 96, 96, 63, 31, 0, //'V'
127, 127, 48, 24, 48, 127, 127, //'W' 127, 127, 48, 24, 48, 127, 127, //'W'
67, 103, 60, 24, 60, 103, 67, //'X' 67, 103, 60, 24, 60, 103, 67, //'X'
7, 79, 120, 120, 79, 7, 0, //'Y' 7, 79, 120, 120, 79, 7, 0, //'Y'
71, 99, 113, 89, 77, 103, 115, //'Z' 71, 99, 113, 89, 77, 103, 115, //'Z'
0, 127, 127, 65, 65, 0, 0, //'[' 0, 127, 127, 65, 65, 0, 0, //'['
1, 3, 6, 12, 24, 48, 96, //'\' 1, 3, 6, 12, 24, 48, 96, //'\'
0, 65, 65, 127, 127, 0, 0, //']' 0, 65, 65, 127, 127, 0, 0, //']'
8, 12, 6, 3, 6, 12, 8, //'^' 8, 12, 6, 3, 6, 12, 8, //'^'
128, 128, 128, 128, 128, 128, 128, //'_' 128, 128, 128, 128, 128, 128, 128, //'_'
0, 0, 3, 7, 4, 0, 0, //'`' 0, 0, 3, 7, 4, 0, 0, //'`'
32, 116, 84, 84, 60, 120, 64, //'a' 32, 116, 84, 84, 60, 120, 64, //'a'
65, 127, 63, 72, 72, 120, 48, //'b' 65, 127, 63, 72, 72, 120, 48, //'b'
56, 124, 68, 68, 108, 40, 0, //'c' 56, 124, 68, 68, 108, 40, 0, //'c'
48, 120, 72, 73, 63, 127, 64, //'d' 48, 120, 72, 73, 63, 127, 64, //'d'
56, 124, 84, 84, 92, 24, 0, //'e' 56, 124, 84, 84, 92, 24, 0, //'e'
72, 126, 127, 73, 3, 2, 0, //'f' 72, 126, 127, 73, 3, 2, 0, //'f'
56, 188, 164, 164, 252, 120, 0, //'g' 56, 188, 164, 164, 252, 120, 0, //'g'
65, 127, 127, 8, 4, 124, 120, //'h' 65, 127, 127, 8, 4, 124, 120, //'h'
0, 68, 125, 125, 64, 0, 0, //'i' 0, 68, 125, 125, 64, 0, 0, //'i'
96, 224, 128, 128, 253, 125, 0, //'j' 96, 224, 128, 128, 253, 125, 0, //'j'
65, 127, 127, 16, 56, 108, 68, //'k' 65, 127, 127, 16, 56, 108, 68, //'k'
0, 65, 127, 127, 64, 0, 0, //'l' 0, 65, 127, 127, 64, 0, 0, //'l'
120, 124, 28, 56, 28, 124, 120, //'m' 120, 124, 28, 56, 28, 124, 120, //'m'
124, 124, 4, 4, 124, 120, 0, //'n' 124, 124, 4, 4, 124, 120, 0, //'n'
56, 124, 68, 68, 124, 56, 0, //'o' 56, 124, 68, 68, 124, 56, 0, //'o'
0, 252, 252, 164, 36, 60, 24, //'p' 0, 252, 252, 164, 36, 60, 24, //'p'
24, 60, 36, 164, 248, 252, 132, //'q' 24, 60, 36, 164, 248, 252, 132, //'q'
68, 124, 120, 76, 4, 28, 24, //'r' 68, 124, 120, 76, 4, 28, 24, //'r'
72, 92, 84, 84, 116, 36, 0, //'s' 72, 92, 84, 84, 116, 36, 0, //'s'
0, 4, 62, 127, 68, 36, 0, //'t' 0, 4, 62, 127, 68, 36, 0, //'t'
60, 124, 64, 64, 60, 124, 64, //'u' 60, 124, 64, 64, 60, 124, 64, //'u'
28, 60, 96, 96, 60, 28, 0, //'v' 28, 60, 96, 96, 60, 28, 0, //'v'
60, 124, 112, 56, 112, 124, 60, //'w' 60, 124, 112, 56, 112, 124, 60, //'w'
68, 108, 56, 16, 56, 108, 68, //'x' 68, 108, 56, 16, 56, 108, 68, //'x'
60, 188, 160, 160, 252, 124, 0, //'y' 60, 188, 160, 160, 252, 124, 0, //'y'
76, 100, 116, 92, 76, 100, 0, //'z' 76, 100, 116, 92, 76, 100, 0, //'z'
8, 8, 62, 119, 65, 65, 0, //'{' 8, 8, 62, 119, 65, 65, 0, //'{'
0, 0, 0, 119, 119, 0, 0, //'|' 0, 0, 0, 119, 119, 0, 0, //'|'
65, 65, 119, 62, 8, 8, 0, //'}' 65, 65, 119, 62, 8, 8, 0, //'}'
2, 3, 1, 3, 2, 3, 1, //'~' 2, 3, 1, 3, 2, 3, 1, //'~'
255, 129, 129, 129, 129, 129, 255, //'^?' 255, 129, 129, 129, 129, 129, 255, //'^?'
14, 159, 145, 177, 251, 74, 0 //'?' 14, 159, 145, 177, 251, 74, 0 //'?'
}; };
/* Global variables */ /* 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 */ /* Character descriptors */
const FONT_CHAR_INFO Ubuntu18ptLengths[] = { const FONT_CHAR_INFO Ubuntu18ptLengths[] = {
{ 2 }, /* */ {2}, /* */
{ 5 }, /* ! */ {5}, /* ! */
{ 7 }, /* " */ {7}, /* " */
{ 38 }, /* # */ {38}, /* # */
{ 26 }, /* $ */ {26}, /* $ */
{ 45 }, /* % */ {45}, /* % */
{ 37 }, /* & */ {37}, /* & */
{ 4 }, /* ' */ {4}, /* ' */
{ 13 }, /* ( */ {13}, /* ( */
{ 12 }, /* ) */ {12}, /* ) */
{ 20 }, /* * */ {20}, /* * */
{ 9 }, /* + */ {9}, /* + */
{ 6 }, /* , */ {6}, /* , */
{ 5 }, /* - */ {5}, /* - */
{ 5 }, /* . */ {5}, /* . */
{ 15 }, /* / */ {15}, /* / */
{ 20 }, /* 0 */ {20}, /* 0 */
{ 10 }, /* 1 */ {10}, /* 1 */
{ 30 }, /* 2 */ {30}, /* 2 */
{ 25 }, /* 3 */ {25}, /* 3 */
{ 24 }, /* 4 */ {24}, /* 4 */
{ 24 }, /* 5 */ {24}, /* 5 */
{ 29 }, /* 6 */ {29}, /* 6 */
{ 21 }, /* 7 */ {21}, /* 7 */
{ 33 }, /* 8 */ {33}, /* 8 */
{ 29 }, /* 9 */ {29}, /* 9 */
{ 6 }, /* : */ {6}, /* : */
{ 8 }, /* ; */ {8}, /* ; */
{ 23 }, /* < */ {23}, /* < */
{ 6 }, /* = */ {6}, /* = */
{ 23 }, /* > */ {23}, /* > */
{ 19 }, /* ? */ {19}, /* ? */
{ 46 }, /* @ */ {46}, /* @ */
{ 29 }, /* A */ {29}, /* A */
{ 21 }, /* B */ {21}, /* B */
{ 21 }, /* C */ {21}, /* C */
{ 18 }, /* D */ {18}, /* D */
{ 10 }, /* E */ {10}, /* E */
{ 10 }, /* F */ {10}, /* F */
{ 21 }, /* G */ {21}, /* G */
{ 10 }, /* H */ {10}, /* H */
{ 5 }, /* I */ {5}, /* I */
{ 13 }, /* J */ {13}, /* J */
{ 28 }, /* K */ {28}, /* K */
{ 7 }, /* L */ {7}, /* L */
{ 28 }, /* M */ {28}, /* M */
{ 22 }, /* N */ {22}, /* N */
{ 28 }, /* O */ {28}, /* O */
{ 19 }, /* P */ {19}, /* P */
{ 40 }, /* Q */ {40}, /* Q */
{ 22 }, /* R */ {22}, /* R */
{ 31 }, /* S */ {31}, /* S */
{ 9 }, /* T */ {9}, /* T */
{ 18 }, /* U */ {18}, /* U */
{ 25 }, /* V */ {25}, /* V */
{ 34 }, /* W */ {34}, /* W */
{ 33 }, /* X */ {33}, /* X */
{ 21 }, /* Y */ {21}, /* Y */
{ 33 }, /* Z */ {33}, /* Z */
{ 8 }, /* [ */ {8}, /* [ */
{ 16 }, /* \ */ {16}, /* \ */
{ 7 }, /* ] */ {7}, /* ] */
{ 19 }, /* ^ */ {19}, /* ^ */
{ 5 }, /* _ */ {5}, /* _ */
{ 10 }, /* ` */ {10}, /* ` */
{ 21 }, /* a */ {21}, /* a */
{ 18 }, /* b */ {18}, /* b */
{ 14 }, /* c */ {14}, /* c */
{ 19 }, /* d */ {19}, /* d */
{ 28 }, /* e */ {28}, /* e */
{ 13 }, /* f */ {13}, /* f */
{ 21 }, /* g */ {21}, /* g */
{ 12 }, /* h */ {12}, /* h */
{ 6 }, /* i */ {6}, /* i */
{ 10 }, /* j */ {10}, /* j */
{ 23 }, /* k */ {23}, /* k */
{ 8 }, /* l */ {8}, /* l */
{ 19 }, /* m */ {19}, /* m */
{ 12 }, /* n */ {12}, /* n */
{ 22 }, /* o */ {22}, /* o */
{ 19 }, /* p */ {19}, /* p */
{ 18 }, /* q */ {18}, /* q */
{ 8 }, /* r */ {8}, /* r */
{ 29 }, /* s */ {29}, /* s */
{ 11 }, /* t */ {11}, /* t */
{ 13 }, /* u */ {13}, /* u */
{ 18 }, /* v */ {18}, /* v */
{ 29 }, /* w */ {29}, /* w */
{ 28 }, /* x */ {28}, /* x */
{ 21 }, /* y */ {21}, /* y */
{ 28 }, /* z */ {28}, /* z */
{ 15 }, /* { */ {15}, /* { */
{ 5 }, /* | */ {5}, /* | */
{ 14 }, /* } */ {14}, /* } */
{ 17 }, /* ~ */ {17}, /* ~ */
{ 32 }, /* Ä */ {32}, /* Ä */
{ 39 }, /* Ö */ {39}, /* Ö */
{ 26 }, /* Ü */ {26}, /* Ü */
{ 31 }, /* ß */ {31}, /* ß */
{ 30 }, /* ä */ {30}, /* ä */
{ 29 }, /* ö */ {29}, /* ö */
{ 19 }, /* ü */ {19}, /* ü */
{ 30 }, /* € */ {30}, /* € */
}; };
const uint16_t Ubuntu18ptExtra[] = { 196, 214, 220, 223, 228, const uint16_t Ubuntu18ptExtra[] = {196, 214, 220, 223, 228, 246, 252, 8364, 65535};
246, 252, 8364, 65535 };
/* Font info */ /* Font info */
const struct FONT_DEF Font_Ubuntu18pt = { 1, /* width (1 == comressed) */ const struct FONT_DEF Font_Ubuntu18pt = {
26, /* character height */ 1, /* width (1 == comressed) */
32, /* first char */ 26, /* character height */
126, /* last char */ 32, /* first char */
Ubuntu18ptBitmaps, 126, /* last char */
Ubuntu18ptLengths, Ubuntu18ptBitmaps,
Ubuntu18ptExtra }; Ubuntu18ptLengths,
Ubuntu18ptExtra};
/* Font metadata: /* Font metadata:
* Name: Ubuntu Regular 18pt * Name: Ubuntu Regular 18pt

View File

@ -34,47 +34,49 @@
#include <sgpio.h> #include <sgpio.h>
#if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O) #if (defined JAWBREAKER || defined HACKRF_ONE || defined RAD1O)
/* /*
* RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on * RF switches on Jawbreaker are controlled by General Purpose Outputs (GPO) on
* the RFFC5072. * the RFFC5072.
* *
* On HackRF One, the same signals are controlled by GPIO on the LPC. * 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 * 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 * on HackRF One as the amplifier power is instead controlled only by
* SWITCHCTRL_AMP_BYPASS. * SWITCHCTRL_AMP_BYPASS.
* *
* The rad1o also uses GPIO pins to control the different switches. The amplifiers * The rad1o also uses GPIO pins to control the different switches. The amplifiers
* are also connected to the LPC. * are also connected to the LPC.
*/ */
#define SWITCHCTRL_NO_TX_AMP_PWR (1 << 0) /* GPO1 turn off TX amp power */ #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_AMP_BYPASS (1 << 1) /* GPO2 bypass amp section */
#define SWITCHCTRL_TX (1 << 2) /* GPO3 1 for TX mode, 0 for RX mode */ #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_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_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 */ #define SWITCHCTRL_NO_RX_AMP_PWR (1 << 5) /* GPO6 turn off RX amp power */
/* /*
GPO6 GPO5 GPO4 GPO3 GPO2 GPO1 GPO6 GPO5 GPO4 GPO3 GPO2 GPO1
!RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode !RXAMP HP MIXBP TX AMPBP !TXAMP Mix mode Amp mode
1 X 1 1 1 1 TX bypass Bypass 1 X 1 1 1 1 TX bypass Bypass
1 X 1 1 0 0 TX bypass TX amplified 1 X 1 1 0 0 TX bypass TX amplified
1 1 0 1 1 1 TX high Bypass 1 1 0 1 1 1 TX high Bypass
1 1 0 1 0 0 TX high TX amplified 1 1 0 1 0 0 TX high TX amplified
1 0 0 1 1 1 TX low Bypass 1 0 0 1 1 1 TX low Bypass
1 0 0 1 0 0 TX low TX amplified 1 0 0 1 0 0 TX low TX amplified
1 X 1 0 1 1 RX bypass Bypass 1 X 1 0 1 1 RX bypass Bypass
0 X 1 0 0 1 RX bypass RX amplified 0 X 1 0 0 1 RX bypass RX amplified
1 1 0 0 1 1 RX high Bypass 1 1 0 0 1 1 RX high Bypass
0 1 0 0 0 1 RX high RX amplified 0 1 0 0 0 1 RX high RX amplified
1 0 0 0 1 1 RX low Bypass 1 0 0 0 1 1 RX low Bypass
0 0 0 0 0 1 RX low RX amplified 0 0 0 0 0 1 RX low RX amplified
*/ */
/* /*
* Safe (initial) switch settings turn off both amplifiers and enable both amp * Safe (initial) switch settings turn off both amplifiers and enable both amp
* bypass and mixer bypass. * bypass and mixer bypass.
*/ */
#define SWITCHCTRL_SAFE (SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR) #define SWITCHCTRL_SAFE \
(SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_TX | \
SWITCHCTRL_MIX_BYPASS | SWITCHCTRL_HP | SWITCHCTRL_NO_RX_AMP_PWR)
#endif #endif
uint8_t switchctrl = SWITCHCTRL_SAFE; uint8_t switchctrl = SWITCHCTRL_SAFE;
@ -88,7 +90,8 @@ uint8_t switchctrl = SWITCHCTRL_SAFE;
#define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */ #define SWITCHCTRL_ANT_PWR (1 << 6) /* turn on antenna port power */
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) { static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl)
{
if (ctrl & SWITCHCTRL_TX) { if (ctrl & SWITCHCTRL_TX) {
gpio_set(rf_path->gpio_tx); gpio_set(rf_path->gpio_tx);
gpio_clear(rf_path->gpio_rx); gpio_clear(rf_path->gpio_rx);
@ -161,7 +164,8 @@ static void switchctrl_set_hackrf_one(rf_path_t* const rf_path, uint8_t ctrl) {
#endif #endif
#ifdef RAD1O #ifdef RAD1O
static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) { static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl)
{
if (ctrl & SWITCHCTRL_TX) { if (ctrl & SWITCHCTRL_TX) {
gpio_set(rf_path->gpio_tx_rx_n); gpio_set(rf_path->gpio_tx_rx_n);
gpio_clear(rf_path->gpio_tx_rx); gpio_clear(rf_path->gpio_tx_rx);
@ -224,7 +228,8 @@ static void switchctrl_set_rad1o(rf_path_t* const rf_path, uint8_t ctrl) {
} }
#endif #endif
static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) { static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo)
{
#ifdef JAWBREAKER #ifdef JAWBREAKER
(void) rf_path; /* silence unused param warning */ (void) rf_path; /* silence unused param warning */
mixer_set_gpo(&mixer, gpo); mixer_set_gpo(&mixer, gpo);
@ -233,11 +238,12 @@ static void switchctrl_set(rf_path_t* const rf_path, const uint8_t gpo) {
#elif RAD1O #elif RAD1O
switchctrl_set_rad1o(rf_path, gpo); switchctrl_set_rad1o(rf_path, gpo);
#else #else
(void)gpo; (void) gpo;
#endif #endif
} }
void rf_path_pin_setup(rf_path_t* const rf_path) { void rf_path_pin_setup(rf_path_t* const rf_path)
{
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
/* Configure RF switch control signals */ /* Configure RF switch control signals */
// clang-format off // clang-format off
@ -257,7 +263,7 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
// clang-format on // clang-format on
/* Configure RF power supply (VAA) switch */ /* Configure RF power supply (VAA) switch */
scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_NO_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
/* Configure RF switch control signals as outputs */ /* Configure RF switch control signals as outputs */
gpio_output(rf_path->gpio_amp_bypass); gpio_output(rf_path->gpio_amp_bypass);
@ -296,7 +302,7 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
// clang-format on // clang-format on
/* Configure RF power supply (VAA) switch */ /* Configure RF power supply (VAA) switch */
scu_pinmux(SCU_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0); scu_pinmux(SCU_VAA_ENABLE, SCU_GPIO_FAST | SCU_CONF_FUNCTION0);
/* Configure RF switch control signals as outputs */ /* Configure RF switch control signals as outputs */
gpio_output(rf_path->gpio_tx_rx_n); gpio_output(rf_path->gpio_tx_rx_n);
@ -321,31 +327,33 @@ void rf_path_pin_setup(rf_path_t* const rf_path) {
#endif #endif
} }
void rf_path_init(rf_path_t* const rf_path) { void rf_path_init(rf_path_t* const rf_path)
{
ssp1_set_mode_max5864(); ssp1_set_mode_max5864();
max5864_setup(&max5864); max5864_setup(&max5864);
max5864_shutdown(&max5864); max5864_shutdown(&max5864);
ssp1_set_mode_max2837(); ssp1_set_mode_max2837();
max2837_setup(&max2837); max2837_setup(&max2837);
max2837_start(&max2837); max2837_start(&max2837);
mixer_setup(&mixer); mixer_setup(&mixer);
switchctrl_set(rf_path, switchctrl); switchctrl_set(rf_path, switchctrl);
} }
void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction) { void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t direction)
{
/* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */ /* Turn off TX and RX amplifiers, then enable based on direction and bypass state. */
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR;
switch(direction) { switch (direction) {
case RF_PATH_DIRECTION_TX: case RF_PATH_DIRECTION_TX:
rf_path->switchctrl |= SWITCHCTRL_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. */ /* TX amplifier is in path, be sure to enable TX amplifier. */
rf_path->switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR; rf_path->switchctrl &= ~SWITCHCTRL_NO_TX_AMP_PWR;
} }
mixer_tx(&mixer); mixer_tx(&mixer);
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) { if (rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS) {
mixer_disable(&mixer); mixer_disable(&mixer);
} else { } else {
mixer_enable(&mixer); mixer_enable(&mixer);
@ -356,15 +364,15 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
max2837_tx(&max2837); max2837_tx(&max2837);
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_TX);
break; break;
case RF_PATH_DIRECTION_RX: case RF_PATH_DIRECTION_RX:
rf_path->switchctrl &= ~SWITCHCTRL_TX; 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. */ /* RX amplifier is in path, be sure to enable RX amplifier. */
rf_path->switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl &= ~SWITCHCTRL_NO_RX_AMP_PWR;
} }
mixer_rx(&mixer); mixer_rx(&mixer);
if( rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS ) { if (rf_path->switchctrl & SWITCHCTRL_MIX_BYPASS) {
mixer_disable(&mixer); mixer_disable(&mixer);
} else { } else {
mixer_enable(&mixer); mixer_enable(&mixer);
@ -375,7 +383,7 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
max2837_rx(&max2837); max2837_rx(&max2837);
sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX); sgpio_configure(&sgpio_config, SGPIO_DIRECTION_RX);
break; break;
case RF_PATH_DIRECTION_OFF: case RF_PATH_DIRECTION_OFF:
default: default:
#ifdef HACKRF_ONE #ifdef HACKRF_ONE
@ -398,19 +406,20 @@ void rf_path_set_direction(rf_path_t* const rf_path, const rf_path_direction_t d
hackrf_ui()->set_direction(direction); hackrf_ui()->set_direction(direction);
} }
void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter) { void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
switch(filter) { {
switch (filter) {
default: default:
case RF_PATH_FILTER_BYPASS: case RF_PATH_FILTER_BYPASS:
rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS; rf_path->switchctrl |= SWITCHCTRL_MIX_BYPASS;
mixer_disable(&mixer); mixer_disable(&mixer);
break; break;
case RF_PATH_FILTER_LOW_PASS: case RF_PATH_FILTER_LOW_PASS:
rf_path->switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS); rf_path->switchctrl &= ~(SWITCHCTRL_HP | SWITCHCTRL_MIX_BYPASS);
mixer_enable(&mixer); mixer_enable(&mixer);
break; break;
case RF_PATH_FILTER_HIGH_PASS: case RF_PATH_FILTER_HIGH_PASS:
rf_path->switchctrl &= ~SWITCHCTRL_MIX_BYPASS; rf_path->switchctrl &= ~SWITCHCTRL_MIX_BYPASS;
rf_path->switchctrl |= SWITCHCTRL_HP; rf_path->switchctrl |= SWITCHCTRL_HP;
@ -423,29 +432,34 @@ void rf_path_set_filter(rf_path_t* const rf_path, const rf_path_filter_t filter)
hackrf_ui()->set_filter(filter); hackrf_ui()->set_filter(filter);
} }
void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable) { void rf_path_set_lna(rf_path_t* const rf_path, const uint_fast8_t enable)
if( enable ) { {
if( rf_path->switchctrl & SWITCHCTRL_TX ) { if (enable) {
if (rf_path->switchctrl & SWITCHCTRL_TX) {
/* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */ /* AMP_BYPASS=0, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=0 */
rf_path->switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_NO_RX_AMP_PWR;
rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR); rf_path->switchctrl &=
~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR);
} else { } else {
/* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */ /* AMP_BYPASS=0, NO_RX_AMP_PWR=0, NO_TX_AMP_PWR=1 */
rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_NO_TX_AMP_PWR;
rf_path->switchctrl &= ~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR); rf_path->switchctrl &=
~(SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_RX_AMP_PWR);
} }
} else { } else {
/* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */ /* AMP_BYPASS=1, NO_RX_AMP_PWR=1, NO_TX_AMP_PWR=1 */
rf_path->switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR | SWITCHCTRL_NO_RX_AMP_PWR; rf_path->switchctrl |= SWITCHCTRL_AMP_BYPASS | SWITCHCTRL_NO_TX_AMP_PWR |
SWITCHCTRL_NO_RX_AMP_PWR;
} }
switchctrl_set(rf_path, rf_path->switchctrl); switchctrl_set(rf_path, rf_path->switchctrl);
hackrf_ui()->set_lna_power(enable); hackrf_ui()->set_lna_power(enable);
} }
/* antenna port power control */ /* antenna port power control */
void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable) { void rf_path_set_antenna(rf_path_t* const rf_path, const uint_fast8_t enable)
{
if (enable) { if (enable) {
rf_path->switchctrl |= SWITCHCTRL_ANT_PWR; rf_path->switchctrl |= SWITCHCTRL_ANT_PWR;
} else { } else {

View File

@ -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_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); 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" #include "hackrf_core.h"
/* Default register values. */ /* Default register values. */
static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = { static const uint16_t rffc5071_regs_default[RFFC5071_NUM_REGS] = {
0xbefa, /* 00 */ 0xbefa, /* 00 */
0x4064, /* 01 */ 0x4064, /* 01 */
0x9055, /* 02 */ 0x9055, /* 02 */
0x2d02, /* 03 */ 0x2d02, /* 03 */
0xacbf, /* 04 */ 0xacbf, /* 04 */
0xacbf, /* 05 */ 0xacbf, /* 05 */
0x0028, /* 06 */ 0x0028, /* 06 */
0x0028, /* 07 */ 0x0028, /* 07 */
0xff00, /* 08 */ 0xff00, /* 08 */
0x8220, /* 09 */ 0x8220, /* 09 */
0x0202, /* 0A */ 0x0202, /* 0A */
0x4800, /* 0B */ 0x4800, /* 0B */
0x1a94, /* 0C */ 0x1a94, /* 0C */
0xd89d, /* 0D */ 0xd89d, /* 0D */
0x8900, /* 0E */ 0x8900, /* 0E */
0x1e84, /* 0F */ 0x1e84, /* 0F */
0x89d8, /* 10 */ 0x89d8, /* 10 */
0x9d00, /* 11 */ 0x9d00, /* 11 */
0x2a20, /* 12 */ 0x2a20, /* 12 */
0x0000, /* 13 */ 0x0000, /* 13 */
0x0000, /* 14 */ 0x0000, /* 14 */
0x0000, /* 15 */ 0x0000, /* 15 */
0x0000, /* 16 */ 0x0000, /* 16 */
0x4900, /* 17 */ 0x4900, /* 17 */
0x0281, /* 18 */ 0x0281, /* 18 */
0xf00f, /* 19 */ 0xf00f, /* 19 */
0x0000, /* 1A */ 0x0000, /* 1A */
0x0000, /* 1B */ 0x0000, /* 1B */
0xc840, /* 1C */ 0xc840, /* 1C */
0x1000, /* 1D */ 0x1000, /* 1D */
0x0005, /* 1E */ }; 0x0005,
/* 1E */};
/* Set up all registers according to defaults specified in docs. */ /* Set up all registers according to defaults specified in docs. */
void rffc5071_init(rffc5071_driver_t* const drv) void rffc5071_init(rffc5071_driver_t* const drv)
@ -120,18 +121,20 @@ void rffc5071_setup(rffc5071_driver_t* const drv)
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r) { static uint16_t rffc5071_spi_read(rffc5071_driver_t* const drv, uint8_t r)
(void)drv; {
(void) drv;
uint16_t data[] = { 0x80 | (r & 0x7f), 0xffff }; uint16_t data[] = {0x80 | (r & 0x7f), 0xffff};
spi_bus_transfer(drv->bus, data, 2); spi_bus_transfer(drv->bus, data, 2);
return data[1]; return data[1];
} }
static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v) { static void rffc5071_spi_write(rffc5071_driver_t* const drv, uint8_t r, uint16_t v)
(void)drv; {
(void) drv;
uint16_t data[] = { 0x00 | (r & 0x7f), v }; uint16_t data[] = {0x00 | (r & 0x7f), v};
spi_bus_transfer(drv->bus, data, 2); spi_bus_transfer(drv->bus, data, 2);
} }
@ -164,21 +167,23 @@ static inline void rffc5071_reg_commit(rffc5071_driver_t* const drv, uint8_t r)
void rffc5071_regs_commit(rffc5071_driver_t* const drv) void rffc5071_regs_commit(rffc5071_driver_t* const drv)
{ {
int r; int r;
for(r = 0; r < RFFC5071_NUM_REGS; r++) { for (r = 0; r < RFFC5071_NUM_REGS; r++) {
if ((drv->regs_dirty >> r) & 0x1) { if ((drv->regs_dirty >> r) & 0x1) {
rffc5071_reg_commit(drv, r); 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_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 0); set_RFFC5071_FULLD(drv, 0);
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
void rffc5071_rx(rffc5071_driver_t* const drv) { void rffc5071_rx(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 0); set_RFFC5071_FULLD(drv, 0);
set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */ set_RFFC5071_MODE(drv, 1); /* mixer 2 used for both RX and TX */
@ -189,7 +194,8 @@ void rffc5071_rx(rffc5071_driver_t* const drv) {
* This function turns on both mixer (full-duplex) on the RFFC5071, but our * This function turns on both mixer (full-duplex) on the RFFC5071, but our
* current hardware designs do not support full-duplex operation. * current hardware designs do not support full-duplex operation.
*/ */
void rffc5071_rxtx(rffc5071_driver_t* const drv) { void rffc5071_rxtx(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */ set_RFFC5071_FULLD(drv, 1); /* mixer 1 and mixer 2 (RXTX) */
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
@ -197,22 +203,25 @@ void rffc5071_rxtx(rffc5071_driver_t* const drv) {
rffc5071_enable(drv); rffc5071_enable(drv);
} }
void rffc5071_disable(rffc5071_driver_t* const drv) { void rffc5071_disable(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 0); set_RFFC5071_ENBL(drv, 0);
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
void rffc5071_enable(rffc5071_driver_t* const drv) { void rffc5071_enable(rffc5071_driver_t* const drv)
{
set_RFFC5071_ENBL(drv, 1); set_RFFC5071_ENBL(drv, 1);
rffc5071_regs_commit(drv); rffc5071_regs_commit(drv);
} }
#define LO_MAX 5400 #define LO_MAX 5400
#define REF_FREQ 40 #define REF_FREQ 40
#define FREQ_ONE_MHZ (1000*1000) #define FREQ_ONE_MHZ (1000 * 1000)
/* configure frequency synthesizer in integer mode (lo in MHz) */ /* configure frequency synthesizer in integer mode (lo in MHz) */
uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) { uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo)
{
uint8_t lodiv; uint8_t lodiv;
uint16_t fvco; uint16_t fvco;
uint8_t fbkdiv; uint8_t fbkdiv;
@ -220,7 +229,7 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
uint64_t tune_freq_hz; uint64_t tune_freq_hz;
uint16_t p1nmsb; uint16_t p1nmsb;
uint8_t p1nlsb; uint8_t p1nlsb;
/* Calculate n_lo */ /* Calculate n_lo */
uint8_t n_lo = 0; uint8_t n_lo = 0;
uint16_t x = LO_MAX / lo; uint16_t x = LO_MAX / lo;
@ -245,14 +254,14 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
set_RFFC5071_PLLCPL(drv, 2); 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; n = tmp_n >> 29ULL;
p1nmsb = (tmp_n >> 13ULL) & 0xffff; p1nmsb = (tmp_n >> 13ULL) & 0xffff;
p1nlsb = (tmp_n >> 5ULL) & 0xff; p1nlsb = (tmp_n >> 5ULL) & 0xff;
tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ) tune_freq_hz = (REF_FREQ * (tmp_n >> 5ULL) * fbkdiv * FREQ_ONE_MHZ) /
/ (lodiv * (1 << 24ULL)); (lodiv * (1 << 24ULL));
/* Path 2 */ /* Path 2 */
set_RFFC5071_P2LODIV(drv, n_lo); set_RFFC5071_P2LODIV(drv, n_lo);
@ -267,7 +276,8 @@ uint64_t rffc5071_config_synth_int(rffc5071_driver_t* const drv, uint16_t lo) {
} }
/* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */ /* !!!!!!!!!!! hz is currently ignored !!!!!!!!!!! */
uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint16_t mhz) { uint64_t rffc5071_set_frequency(rffc5071_driver_t* const drv, uint16_t mhz)
{
uint32_t tune_freq; uint32_t tune_freq;
rffc5071_disable(drv); rffc5071_disable(drv);

View File

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

View File

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

View File

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

View File

@ -95,21 +95,19 @@ typedef enum
/* Special Error */ /* Special Error */
ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */ ERROR_IAP_NOT_IMPLEMENTED = 0x00000100 /* IAP is not implemented in this part */
} isp_iap_ret_code_t; } isp_iap_ret_code_t;
// clang-format on // clang-format on
typedef struct typedef struct {
{
/* Input Command/Param */ /* Input Command/Param */
struct struct {
{
iap_cmd_code_t command_code; iap_cmd_code_t command_code;
uint32_t iap_param[5]; uint32_t iap_param[5];
} cmd_param; } cmd_param;
/* Output Status/Result */ /* Output Status/Result */
struct struct {
{ isp_iap_ret_code_t status_ret;
isp_iap_ret_code_t status_ret;
uint32_t iap_result[4]; uint32_t iap_result[4];
} status_res; } status_res;
} iap_cmd_res_t; } iap_cmd_res_t;
@ -119,4 +117,4 @@ bool iap_is_implemented(void);
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);
#endif//__ROM_IAP__ #endif //__ROM_IAP__

View File

@ -630,9 +630,8 @@ EV[0:15]_CTRL[MATCHMEM, DIRECTION]
/* -- SCT_OUTPUTDIRCTRL_SETCLR10: Set/clear operation on output 5. Value 0x3 is /* -- SCT_OUTPUTDIRCTRL_SETCLR10: Set/clear operation on output 5. Value 0x3 is
* reserved. Do not program this value. */ * reserved. Do not program this value. */
#define SCT_OUTPUTDIRCTRL_SETCLR10_SHIFT (20) #define SCT_OUTPUTDIRCTRL_SETCLR10_SHIFT (20)
#define SCT_OUTPUTDIRCTRL_SETCLR10_MASK \ #define SCT_OUTPUTDIRCTRL_SETCLR10_MASK (0x03 << SCT_OUTPUTDIRCTRL_SETCLR10_SHIFT)
(0x03 << SCT_OUTPUTDIRCTRL_SETCLR10_SHIFT) #define SCT_OUTPUTDIRCTRL_SETCLR10(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR10_SHIFT)
#define SCT_OUTPUTDIRCTRL_SETCLR10(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR10_SHIFT)
/* SCT_OUTPUTDIRCTRL_SETCLR10_SETCLR10 values */ /* SCT_OUTPUTDIRCTRL_SETCLR10_SETCLR10 values */
/* Independent. Set and clear do not depend on any counter. */ /* Independent. Set and clear do not depend on any counter. */
@ -647,9 +646,8 @@ EV[0:15]_CTRL[MATCHMEM, DIRECTION]
/* -- SCT_OUTPUTDIRCTRL_SETCLR11: Set/clear operation on output 11. Value 0x3 is /* -- SCT_OUTPUTDIRCTRL_SETCLR11: Set/clear operation on output 11. Value 0x3 is
* reserved. Do not program this value. */ * reserved. Do not program this value. */
#define SCT_OUTPUTDIRCTRL_SETCLR11_SHIFT (22) #define SCT_OUTPUTDIRCTRL_SETCLR11_SHIFT (22)
#define SCT_OUTPUTDIRCTRL_SETCLR11_MASK \ #define SCT_OUTPUTDIRCTRL_SETCLR11_MASK (0x03 << SCT_OUTPUTDIRCTRL_SETCLR11_SHIFT)
(0x03 << SCT_OUTPUTDIRCTRL_SETCLR11_SHIFT) #define SCT_OUTPUTDIRCTRL_SETCLR11(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR11_SHIFT)
#define SCT_OUTPUTDIRCTRL_SETCLR11(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR11_SHIFT)
/* SCT_OUTPUTDIRCTRL_SETCLR11_SETCLR11 values */ /* SCT_OUTPUTDIRCTRL_SETCLR11_SETCLR11 values */
/* Independent. Set and clear do not depend on any counter. */ /* Independent. Set and clear do not depend on any counter. */
@ -664,9 +662,8 @@ EV[0:15]_CTRL[MATCHMEM, DIRECTION]
/* -- SCT_OUTPUTDIRCTRL_SETCLR12: Set/clear operation on output 12. Value 0x3 is /* -- SCT_OUTPUTDIRCTRL_SETCLR12: Set/clear operation on output 12. Value 0x3 is
* reserved. Do not program this value. */ * reserved. Do not program this value. */
#define SCT_OUTPUTDIRCTRL_SETCLR12_SHIFT (24) #define SCT_OUTPUTDIRCTRL_SETCLR12_SHIFT (24)
#define SCT_OUTPUTDIRCTRL_SETCLR12_MASK \ #define SCT_OUTPUTDIRCTRL_SETCLR12_MASK (0x03 << SCT_OUTPUTDIRCTRL_SETCLR12_SHIFT)
(0x03 << SCT_OUTPUTDIRCTRL_SETCLR12_SHIFT) #define SCT_OUTPUTDIRCTRL_SETCLR12(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR12_SHIFT)
#define SCT_OUTPUTDIRCTRL_SETCLR12(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR12_SHIFT)
/* SCT_OUTPUTDIRCTRL_SETCLR12_SETCLR12 values */ /* SCT_OUTPUTDIRCTRL_SETCLR12_SETCLR12 values */
/* Independent. Set and clear do not depend on any counter. */ /* Independent. Set and clear do not depend on any counter. */
@ -681,9 +678,8 @@ EV[0:15]_CTRL[MATCHMEM, DIRECTION]
/* -- SCT_OUTPUTDIRCTRL_SETCLR13: Set/clear operation on output 13. Value 0x3 is /* -- SCT_OUTPUTDIRCTRL_SETCLR13: Set/clear operation on output 13. Value 0x3 is
* reserved. Do not program this value. */ * reserved. Do not program this value. */
#define SCT_OUTPUTDIRCTRL_SETCLR13_SHIFT (26) #define SCT_OUTPUTDIRCTRL_SETCLR13_SHIFT (26)
#define SCT_OUTPUTDIRCTRL_SETCLR13_MASK \ #define SCT_OUTPUTDIRCTRL_SETCLR13_MASK (0x03 << SCT_OUTPUTDIRCTRL_SETCLR13_SHIFT)
(0x03 << SCT_OUTPUTDIRCTRL_SETCLR13_SHIFT) #define SCT_OUTPUTDIRCTRL_SETCLR13(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR13_SHIFT)
#define SCT_OUTPUTDIRCTRL_SETCLR13(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR13_SHIFT)
/* SCT_OUTPUTDIRCTRL_SETCLR13_SETCLR13 values */ /* SCT_OUTPUTDIRCTRL_SETCLR13_SETCLR13 values */
/* Independent. Set and clear do not depend on any counter. */ /* Independent. Set and clear do not depend on any counter. */
@ -698,9 +694,8 @@ EV[0:15]_CTRL[MATCHMEM, DIRECTION]
/* -- SCT_OUTPUTDIRCTRL_SETCLR14: Set/clear operation on output 14. Value 0x3 is /* -- SCT_OUTPUTDIRCTRL_SETCLR14: Set/clear operation on output 14. Value 0x3 is
* reserved. Do not program this value. */ * reserved. Do not program this value. */
#define SCT_OUTPUTDIRCTRL_SETCLR14_SHIFT (28) #define SCT_OUTPUTDIRCTRL_SETCLR14_SHIFT (28)
#define SCT_OUTPUTDIRCTRL_SETCLR14_MASK \ #define SCT_OUTPUTDIRCTRL_SETCLR14_MASK (0x03 << SCT_OUTPUTDIRCTRL_SETCLR14_SHIFT)
(0x03 << SCT_OUTPUTDIRCTRL_SETCLR14_SHIFT) #define SCT_OUTPUTDIRCTRL_SETCLR14(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR14_SHIFT)
#define SCT_OUTPUTDIRCTRL_SETCLR14(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR14_SHIFT)
/* SCT_OUTPUTDIRCTRL_SETCLR14_SETCLR14 values */ /* SCT_OUTPUTDIRCTRL_SETCLR14_SETCLR14 values */
/* Independent. Set and clear do not depend on any counter. */ /* Independent. Set and clear do not depend on any counter. */
@ -715,9 +710,8 @@ EV[0:15]_CTRL[MATCHMEM, DIRECTION]
/* -- SCT_OUTPUTDIRCTRL_SETCLR15: Set/clear operation on output 15. Value 0x3 is /* -- SCT_OUTPUTDIRCTRL_SETCLR15: Set/clear operation on output 15. Value 0x3 is
* reserved. Do not program this value. */ * reserved. Do not program this value. */
#define SCT_OUTPUTDIRCTRL_SETCLR15_SHIFT (30) #define SCT_OUTPUTDIRCTRL_SETCLR15_SHIFT (30)
#define SCT_OUTPUTDIRCTRL_SETCLR15_MASK \ #define SCT_OUTPUTDIRCTRL_SETCLR15_MASK (0x03 << SCT_OUTPUTDIRCTRL_SETCLR15_SHIFT)
(0x03 << SCT_OUTPUTDIRCTRL_SETCLR15_SHIFT) #define SCT_OUTPUTDIRCTRL_SETCLR15(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR15_SHIFT)
#define SCT_OUTPUTDIRCTRL_SETCLR15(x) ((x) << SCT_OUTPUTDIRCTRL_SETCLR15_SHIFT)
/* SCT_OUTPUTDIRCTRL_SETCLR15_SETCLR15 values */ /* SCT_OUTPUTDIRCTRL_SETCLR15_SETCLR15 values */
/* Independent. Set and clear do not depend on any counter. */ /* Independent. Set and clear do not depend on any counter. */

View File

@ -32,7 +32,8 @@
static void update_q_invert(sgpio_config_t* const config); static void update_q_invert(sgpio_config_t* const config);
#endif #endif
void sgpio_configure_pin_functions(sgpio_config_t* const config) { void sgpio_configure_pin_functions(sgpio_config_t* const config)
{
scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); scu_pinmux(SCU_PINMUX_SGPIO0, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3); scu_pinmux(SCU_PINMUX_SGPIO1, SCU_GPIO_FAST | SCU_CONF_FUNCTION3);
scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2); scu_pinmux(SCU_PINMUX_SGPIO2, SCU_GPIO_FAST | SCU_CONF_FUNCTION2);
@ -46,21 +47,19 @@ 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_SGPIO10, SCU_GPIO_FAST | SCU_CONF_FUNCTION6);
scu_pinmux(SCU_PINMUX_SGPIO11, 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_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_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_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_SGPIO15, SCU_GPIO_FAST | SCU_CONF_FUNCTION4); /* GPIO5[14] */
sgpio_cpld_stream_rx_set_q_invert(config, 0); 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_rx_q_invert);
gpio_output(config->gpio_hw_sync_enable); gpio_output(config->gpio_hw_sync_enable);
} }
void sgpio_set_slice_mode( void sgpio_set_slice_mode(sgpio_config_t* const config, const bool multi_slice)
sgpio_config_t* const config, {
const bool multi_slice
) {
config->slice_mode_multislice = multi_slice; config->slice_mode_multislice = multi_slice;
} }
@ -95,16 +94,13 @@ void sgpio_set_slice_mode(
SGPIO10 Disable Output (1/High=Disable codec data stream, 0/Low=Enable codec data stream) SGPIO10 Disable Output (1/High=Disable codec data stream, 0/Low=Enable codec data stream)
SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC) SGPIO11 Direction Output (1/High=TX mode LPC43xx=>CPLD=>DAC, 0/Low=RX mode LPC43xx<=CPLD<=ADC)
*/ */
void sgpio_configure( void sgpio_configure(sgpio_config_t* const config, const sgpio_direction_t direction)
sgpio_config_t* const config, {
const sgpio_direction_t direction
) {
// Disable all counters during configuration // Disable all counters during configuration
SGPIO_CTRL_ENABLE = 0; SGPIO_CTRL_ENABLE = 0;
// Set SGPIO output values. // Set SGPIO output values.
const uint_fast8_t cpld_direction = const uint_fast8_t cpld_direction = (direction == SGPIO_DIRECTION_TX) ? 1 : 0;
(direction == SGPIO_DIRECTION_TX) ? 1 : 0;
// clang-format off // clang-format off
SGPIO_GPIO_OUTREG = SGPIO_GPIO_OUTREG =
@ -123,9 +119,7 @@ void sgpio_configure(
// Enable SGPIO pin outputs. // Enable SGPIO pin outputs.
const uint_fast16_t sgpio_gpio_data_direction = const uint_fast16_t sgpio_gpio_data_direction =
(direction == SGPIO_DIRECTION_TX) (direction == SGPIO_DIRECTION_TX) ? (0xFF << 0) : (0x00 << 0);
? (0xFF << 0)
: (0x00 << 0);
// clang-format off // clang-format off
SGPIO_GPIO_OENREG = SGPIO_GPIO_OENREG =
@ -162,7 +156,7 @@ void sgpio_configure(
const uint_fast8_t output_multiplexing_mode = const uint_fast8_t output_multiplexing_mode =
config->slice_mode_multislice ? 11 : 9; config->slice_mode_multislice ? 11 : 9;
/* SGPIO0 to SGPIO7 */ /* SGPIO0 to SGPIO7 */
for(uint_fast8_t i=0; i<8; i++) { for (uint_fast8_t i = 0; i < 8; i++) {
// SGPIO pin 0 outputs slice A bit "i". // SGPIO pin 0 outputs slice A bit "i".
SGPIO_OUT_MUX_CFG(i) = SGPIO_OUT_MUX_CFG_P_OE_CFG(0) 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) // 11 = dout_doutm8c (8-bit mode 8c) (multislice L0/7, N0/7)
@ -181,17 +175,16 @@ void sgpio_configure(
SGPIO_SLICE_L, SGPIO_SLICE_L,
}; };
const uint_fast8_t slice_gpdma = SGPIO_SLICE_H; const uint_fast8_t slice_gpdma = SGPIO_SLICE_H;
const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03; const uint_fast8_t pos = config->slice_mode_multislice ? 0x1f : 0x03;
const bool single_slice = !config->slice_mode_multislice; const bool single_slice = !config->slice_mode_multislice;
const uint_fast8_t slice_count = config->slice_mode_multislice ? 8 : 1; const uint_fast8_t slice_count = config->slice_mode_multislice ? 8 : 1;
// Also enable slice D for clkout to the SCTimer // Also enable slice D for clkout to the SCTimer
uint32_t slice_enable_mask = BIT3; uint32_t slice_enable_mask = BIT3;
/* Configure Slice A, I, E, J, C, K, F, L (sgpio_slice_mode_multislice mode) */ /* Configure Slice A, I, E, J, C, K, F, L (sgpio_slice_mode_multislice mode) */
for(uint_fast8_t i=0; i<slice_count; i++) for (uint_fast8_t i = 0; i < slice_count; i++) {
{
const uint_fast8_t slice_index = slice_indices[i]; const uint_fast8_t slice_index = slice_indices[i];
/* Only for slice0/A and RX mode set input_slice to 1 */ /* Only for slice0/A and RX mode set input_slice to 1 */
const bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX); const bool input_slice = (i == 0) && (direction != SGPIO_DIRECTION_TX);
@ -199,7 +192,7 @@ void sgpio_configure(
const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3; const uint_fast8_t concat_order = (input_slice || single_slice) ? 0 : 3;
/* 0 = External data pin (slice0/A RX mode), 1 = Concatenate data */ /* 0 = External data pin (slice0/A RX mode), 1 = Concatenate data */
const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1; const uint_fast8_t concat_enable = (input_slice || single_slice) ? 0 : 1;
// clang-format off // clang-format off
SGPIO_MUX_CFG(slice_index) = SGPIO_MUX_CFG(slice_index) =
SGPIO_MUX_CFG_CONCAT_ORDER(concat_order) SGPIO_MUX_CFG_CONCAT_ORDER(concat_order)
@ -222,20 +215,17 @@ void sgpio_configure(
; ;
// clang-format on // clang-format on
SGPIO_PRESET(slice_index) = 0; // External clock, don't care SGPIO_PRESET(slice_index) = 0; // External clock, don't care
SGPIO_COUNT(slice_index) = 0; // External clock, don't care SGPIO_COUNT(slice_index) = 0; // External clock, don't care
SGPIO_POS(slice_index) = SGPIO_POS(slice_index) = SGPIO_POS_POS_RESET(pos) | SGPIO_POS_POS(pos);
SGPIO_POS_POS_RESET(pos) SGPIO_REG(slice_index) = 0x00000000; // Primary output data register
| SGPIO_POS_POS(pos) SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register
;
SGPIO_REG(slice_index) = 0x00000000; // Primary output data register
SGPIO_REG_SS(slice_index) = 0x00000000; // Shadow output data register
// clang-format on // clang-format on
slice_enable_mask |= (1 << slice_index); slice_enable_mask |= (1 << slice_index);
} }
if( config->slice_mode_multislice == false ) { if (config->slice_mode_multislice == false) {
// clang-format off // clang-format off
SGPIO_MUX_CFG(slice_gpdma) = SGPIO_MUX_CFG(slice_gpdma) =
SGPIO_MUX_CFG_CONCAT_ORDER(0) // Self-loop SGPIO_MUX_CFG_CONCAT_ORDER(0) // Self-loop
@ -258,15 +248,14 @@ void sgpio_configure(
; ;
// clang-format on // clang-format on
SGPIO_PRESET(slice_gpdma) = 0; // External clock, don't care SGPIO_PRESET(slice_gpdma) = 0; // External clock, don't care
SGPIO_COUNT(slice_gpdma) = 0; // External clock, don't care SGPIO_COUNT(slice_gpdma) = 0; // External clock, don't care
SGPIO_POS(slice_gpdma) = SGPIO_POS(slice_gpdma) = SGPIO_POS_POS_RESET(0x1f) | SGPIO_POS_POS(0x1f);
SGPIO_POS_POS_RESET(0x1f) SGPIO_REG(slice_gpdma) =
| SGPIO_POS_POS(0x1f) 0x11111111; // Primary output data register, LSB -> out
; SGPIO_REG_SS(slice_gpdma) =
SGPIO_REG(slice_gpdma) = 0x11111111; // Primary output data register, LSB -> out 0x11111111; // Shadow output data register, LSB -> out1
SGPIO_REG_SS(slice_gpdma) = 0x11111111; // Shadow output data register, LSB -> out1
slice_enable_mask |= (1 << slice_gpdma); slice_enable_mask |= (1 << slice_gpdma);
} }
@ -274,24 +263,26 @@ void sgpio_configure(
SGPIO_CTRL_ENABLE = slice_enable_mask; SGPIO_CTRL_ENABLE = slice_enable_mask;
} }
void sgpio_cpld_stream_enable(sgpio_config_t* const config) { void sgpio_cpld_stream_enable(sgpio_config_t* const config)
(void)config; {
(void) config;
// Enable codec data stream. // Enable codec data stream.
SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */ SGPIO_GPIO_OUTREG &= ~(1L << 10); /* SGPIO10 */
} }
void sgpio_cpld_stream_disable(sgpio_config_t* const config) { void sgpio_cpld_stream_disable(sgpio_config_t* const config)
(void)config; {
(void) config;
// Disable codec data stream. // Disable codec data stream.
SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */ SGPIO_GPIO_OUTREG |= (1L << 10); /* SGPIO10 */
} }
bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config) { bool sgpio_cpld_stream_is_enabled(sgpio_config_t* const config)
(void)config; {
(void) config;
return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */ return (SGPIO_GPIO_OUTREG & (1L << 10)) == 0; /* SGPIO10 */
} }
#ifdef RAD1O #ifdef RAD1O
/* The rad1o hardware has a bug which makes it /* The rad1o hardware has a bug which makes it
* necessary to also switch between the two options based * necessary to also switch between the two options based
@ -306,24 +297,28 @@ static bool sgpio_invert = false;
/* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert /* Called when TX/RX changes od sgpio_cpld_stream_rx_set_q_invert
* gets called. */ * gets called. */
static void update_q_invert(sgpio_config_t* const config) { static void update_q_invert(sgpio_config_t* const config)
{
/* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */ /* 1=Output SGPIO11 High(TX mode), 0=Output SGPIO11 Low(RX mode) */
bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0; bool tx_mode = (SGPIO_GPIO_OUTREG & (1 << 11)) > 0;
/* 0.13: P1_18 */ /* 0.13: P1_18 */
if( !sgpio_invert & !tx_mode) { if (!sgpio_invert & !tx_mode) {
gpio_write(config->gpio_rx_q_invert, 1); 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); 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); 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); 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) { void sgpio_cpld_stream_rx_set_q_invert(
if( invert ) { sgpio_config_t* const config,
const uint_fast8_t invert)
{
if (invert) {
sgpio_invert = true; sgpio_invert = true;
} else { } else {
sgpio_invert = false; sgpio_invert = false;
@ -333,7 +328,10 @@ void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_
} }
#else #else
void sgpio_cpld_stream_rx_set_q_invert(sgpio_config_t* const config, const uint_fast8_t invert) { void sgpio_cpld_stream_rx_set_q_invert(
sgpio_config_t* const config,
const uint_fast8_t invert)
{
gpio_write(config->gpio_rx_q_invert, invert); gpio_write(config->gpio_rx_q_invert, invert);
} }
#endif #endif

View File

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

View File

@ -29,15 +29,15 @@ uint8_t clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
/* write to single register */ /* write to single register */
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val) void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val)
{ {
const uint8_t data_tx[] = { reg, val }; const uint8_t data_tx[] = {reg, val};
si5351c_write(drv, data_tx, 2); si5351c_write(drv, data_tx, 2);
} }
/* read single register */ /* read single register */
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg) uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg)
{ {
const uint8_t data_tx[] = { reg }; const uint8_t data_tx[] = {reg};
uint8_t data_rx[] = { 0x00 }; uint8_t data_rx[] = {0x00};
i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1); i2c_bus_transfer(drv->bus, drv->i2c_address, data_tx, 1, data_rx, 1);
return data_rx[0]; 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 * Write to one or more contiguous registers. data[0] should be the first
* register number, one or more values follow. * register number, one or more values follow.
*/ */
void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count) void si5351c_write(
si5351c_driver_t* const drv,
const uint8_t* const data,
const size_t data_count)
{ {
i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0); i2c_bus_transfer(drv->bus, drv->i2c_address, data, data_count, NULL, 0);
} }
@ -54,30 +57,30 @@ void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const
/* Disable all CLKx outputs. */ /* Disable all CLKx outputs. */
void si5351c_disable_all_outputs(si5351c_driver_t* const drv) 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)); si5351c_write(drv, data, sizeof(data));
} }
/* Turn off OEB pin control for all CLKx */ /* Turn off OEB pin control for all CLKx */
void si5351c_disable_oeb_pin_control(si5351c_driver_t* const drv) 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)); si5351c_write(drv, data, sizeof(data));
} }
/* Power down all CLKx */ /* Power down all CLKx */
void si5351c_power_down_all_clocks(si5351c_driver_t* const drv) void si5351c_power_down_all_clocks(si5351c_driver_t* const drv)
{ {
uint8_t data[] = { 16 uint8_t data[] = {
, SI5351C_CLK_POWERDOWN 16,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE SI5351C_CLK_POWERDOWN,
, SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE,
}; SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
@ -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) 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)); 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) 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)); 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) 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)); 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) void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv)
{ {
/*PLLA: 25MHz XTAL * (0x0e00+512)/128 = 800mhz -> int mode */ /*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)); si5351c_write(drv, data, sizeof(data));
/*PLLB: 10MHz CLKIN * (0x2600+512)/128 = 800mhz */ /*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) void si5351c_reset_pll(si5351c_driver_t* const drv)
{ {
/* reset PLLA and PLLB */ /* reset PLLA and PLLB */
uint8_t data[] = { 177, 0xA0 }; uint8_t data[] = {177, 0xA0};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
void si5351c_configure_multisynth(si5351c_driver_t* const drv, void si5351c_configure_multisynth(
const uint_fast8_t ms_number, si5351c_driver_t* const drv,
const uint32_t p1, const uint32_t p2, const uint32_t p3, const uint_fast8_t ms_number,
const uint_fast8_t r_div) 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? * 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); const uint_fast8_t register_number = 42 + (ms_number * 8);
uint8_t data[] = { uint8_t data[] = {
register_number, register_number,
(p3 >> 8) & 0xFF, (p3 >> 8) & 0xFF,
(p3 >> 0) & 0xFF, (p3 >> 0) & 0xFF,
(r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3), (r_div << 4) | (0 << 2) | ((p1 >> 16) & 0x3),
(p1 >> 8) & 0xFF, (p1 >> 8) & 0xFF,
(p1 >> 0) & 0xFF, (p1 >> 0) & 0xFF,
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0), (((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0),
(p2 >> 8) & 0xFF, (p2 >> 8) & 0xFF,
(p2 >> 0) & 0xFF }; (p2 >> 0) & 0xFF};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source) void si5351c_configure_clock_control(
si5351c_driver_t* const drv,
const enum pll_sources source)
{ {
uint8_t pll; uint8_t pll;
#ifdef RAD1O #ifdef RAD1O
@ -186,23 +194,37 @@ void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll
#endif #endif
/* Clock to CPU is deactivated as it is not used and creates noise */ /* Clock to CPU is deactivated as it is not used and creates noise */
/* External clock output is kept in current state */ /* External clock output is kept in current state */
uint8_t data[] = {16 uint8_t data[] = {
,SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA) 16,
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV SI5351C_CLK_FRAC_MODE | SI5351C_CLK_PLL_SRC(pll) |
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
,clk3_ctrl SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA),
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
,SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) | SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) | SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA) SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA) | SI5351C_CLK_INV,
,SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/ SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
}; SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_0_4) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_2MA),
clk3_ctrl,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_6MA) | SI5351C_CLK_INV,
SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_4MA),
SI5351C_CLK_POWERDOWN |
SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
,
SI5351C_CLK_POWERDOWN |
SI5351C_CLK_INT_MODE /*not connected, but: plla int mode*/
};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
#define SI5351C_CLK_ENABLE(x) (0<<x) #define SI5351C_CLK_ENABLE(x) (0 << x)
#define SI5351C_CLK_DISABLE(x) (1<<x) #define SI5351C_CLK_DISABLE(x) (1 << x)
#define SI5351C_REG_OUTPUT_EN (3) #define SI5351C_REG_OUTPUT_EN (3)
#define SI5351C_REG_CLK3_CTRL (19) #define SI5351C_REG_CLK3_CTRL (19)
void si5351c_enable_clock_outputs(si5351c_driver_t* const drv) void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
{ {
@ -210,44 +232,45 @@ void si5351c_enable_clock_outputs(si5351c_driver_t* const drv)
/* 7: Clock to CPU is deactivated as it is not used and creates noise */ /* 7: Clock to CPU is deactivated as it is not used and creates noise */
/* 3: External clock output is deactivated by default */ /* 3: External clock output is deactivated by default */
// uint8_t data[] = { 3, ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5))}; // uint8_t data[] = { 3, ~((1 << 0) | (1 << 1) | (1 << 2) | (1 << 4) | (1 << 5))};
uint8_t data[] = { SI5351C_REG_OUTPUT_EN, uint8_t data[] = {
SI5351C_CLK_ENABLE(0) | SI5351C_REG_OUTPUT_EN,
SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(0) | SI5351C_CLK_ENABLE(1) | SI5351C_CLK_ENABLE(2) |
SI5351C_CLK_ENABLE(2) | SI5351C_CLK_DISABLE(3) | SI5351C_CLK_ENABLE(4) |
SI5351C_CLK_DISABLE(3) | SI5351C_CLK_ENABLE(5) | SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_ENABLE(4) | SI5351C_CLK_DISABLE(7)};
SI5351C_CLK_ENABLE(5) |
SI5351C_CLK_DISABLE(6) |
SI5351C_CLK_DISABLE(7)
};
si5351c_write(drv, data, sizeof(data)); si5351c_write(drv, data, sizeof(data));
} }
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on){ void si5351c_set_int_mode(
uint8_t data[] = {16, 0}; 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){ if (ms_number < 8) {
data[0] = 16 + ms_number; data[0] = 16 + ms_number;
data[1] = si5351c_read_single(drv, data[0]); data[1] = si5351c_read_single(drv, data[0]);
if(on) if (on)
data[1] |= SI5351C_CLK_INT_MODE; data[1] |= SI5351C_CLK_INT_MODE;
else else
data[1] &= ~(SI5351C_CLK_INT_MODE); data[1] &= ~(SI5351C_CLK_INT_MODE);
si5351c_write(drv, data, 2); si5351c_write(drv, data, 2);
} }
} }
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source) void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source)
{ {
if( source != active_clock_source ) { if (source != active_clock_source) {
si5351c_configure_clock_control(drv, source); si5351c_configure_clock_control(drv, source);
active_clock_source = 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; return (si5351c_read_single(drv, 0) & SI5351C_LOS) == 0;
} }
@ -256,7 +279,7 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
/* Set optput in output enable register */ /* Set optput in output enable register */
uint8_t output_enable = si5351c_read_single(drv, 3); uint8_t output_enable = si5351c_read_single(drv, 3);
output_enable = output_enable & !SI5351C_CLK_DISABLE(3); output_enable = output_enable & !SI5351C_CLK_DISABLE(3);
if(enable) if (enable)
output_enable = output_enable | SI5351C_CLK_ENABLE(3); output_enable = output_enable | SI5351C_CLK_ENABLE(3);
else else
output_enable = output_enable | SI5351C_CLK_DISABLE(3); output_enable = output_enable | SI5351C_CLK_DISABLE(3);
@ -264,26 +287,28 @@ void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable)
si5351c_write(drv, oe_data, 2); si5351c_write(drv, oe_data, 2);
/* Configure clock to 10MHz (TODO customisable?) */ /* 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*/ /* Set power up/doen in CLK3 control register*/
uint8_t pll; 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 */ /* PLLA on XTAL */
pll = SI5351C_CLK_PLL_SRC_A; pll = SI5351C_CLK_PLL_SRC_A;
#endif }
#endif
#if (defined JAWBREAKER || defined HACKRF_ONE) if (enable)
if (active_clock_source == PLL_SOURCE_CLKIN) { clk3_ctrl = SI5351C_CLK_INT_MODE | SI5351C_CLK_PLL_SRC(pll) |
/* PLLB on CLKIN */ SI5351C_CLK_SRC(SI5351C_CLK_SRC_MULTISYNTH_SELF) |
pll = SI5351C_CLK_PLL_SRC_B; SI5351C_CLK_IDRV(SI5351C_CLK_IDRV_8MA);
} 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 else
clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE; clk3_ctrl = SI5351C_CLK_POWERDOWN | SI5351C_CLK_INT_MODE;
uint8_t clk3_data[] = {SI5351C_REG_CLK3_CTRL, clk3_ctrl}; uint8_t clk3_data[] = {SI5351C_REG_CLK3_CTRL, clk3_ctrl};

View File

@ -24,8 +24,7 @@
#define __SI5351C_H #define __SI5351C_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C" {
{
#endif #endif
#include <stdint.h> #include <stdint.h>
@ -33,31 +32,31 @@ extern "C"
#include "i2c_bus.h" #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_POWERDOWN (1 << 7)
#define SI5351C_CLK_INT_MODE (1<<6) #define SI5351C_CLK_INT_MODE (1 << 6)
#define SI5351C_CLK_FRAC_MODE (0<<6) #define SI5351C_CLK_FRAC_MODE (0 << 6)
#define SI5351C_CLK_PLL_SRC(x) (x<<5) #define SI5351C_CLK_PLL_SRC(x) (x << 5)
#define SI5351C_CLK_PLL_SRC_A 0 #define SI5351C_CLK_PLL_SRC_A 0
#define SI5351C_CLK_PLL_SRC_B 1 #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(x) (x << 2)
#define SI5351C_CLK_SRC_XTAL 0 #define SI5351C_CLK_SRC_XTAL 0
#define SI5351C_CLK_SRC_CLKIN 1 #define SI5351C_CLK_SRC_CLKIN 1
#define SI5351C_CLK_SRC_MULTISYNTH_0_4 2 #define SI5351C_CLK_SRC_MULTISYNTH_0_4 2
#define SI5351C_CLK_SRC_MULTISYNTH_SELF 3 #define SI5351C_CLK_SRC_MULTISYNTH_SELF 3
#define SI5351C_CLK_IDRV(x) (x<<0) #define SI5351C_CLK_IDRV(x) (x << 0)
#define SI5351C_CLK_IDRV_2MA 0 #define SI5351C_CLK_IDRV_2MA 0
#define SI5351C_CLK_IDRV_4MA 1 #define SI5351C_CLK_IDRV_4MA 1
#define SI5351C_CLK_IDRV_6MA 2 #define SI5351C_CLK_IDRV_6MA 2
#define SI5351C_CLK_IDRV_8MA 3 #define SI5351C_CLK_IDRV_8MA 3
#define SI5351C_LOS (1<<4) #define SI5351C_LOS (1 << 4)
enum pll_sources { enum pll_sources {
PLL_SOURCE_UNINITIALIZED = -1, 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_sources(si5351c_driver_t* const drv);
void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv); void si5351c_configure_pll_multisynth(si5351c_driver_t* const drv);
void si5351c_reset_pll(si5351c_driver_t* const drv); void si5351c_reset_pll(si5351c_driver_t* const drv);
void si5351c_configure_multisynth(si5351c_driver_t* const drv, void si5351c_configure_multisynth(
const uint_fast8_t ms_number, si5351c_driver_t* const drv,
const uint32_t p1, const uint32_t p2, const uint32_t p3, const uint_fast8_t ms_number,
const uint_fast8_t r_div); const uint32_t p1,
void si5351c_configure_clock_control(si5351c_driver_t* const drv, const enum pll_sources source); 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_enable_clock_outputs(si5351c_driver_t* const drv);
void si5351c_set_int_mode(si5351c_driver_t* const drv, const uint_fast8_t ms_number, const uint_fast8_t on); void si5351c_set_int_mode(
si5351c_driver_t* const drv,
const uint_fast8_t ms_number,
const uint_fast8_t on);
void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source); void si5351c_set_clock_source(si5351c_driver_t* const drv, const enum pll_sources source);
bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv); bool si5351c_clkin_signal_valid(si5351c_driver_t* const drv);
void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val); void si5351c_write_single(si5351c_driver_t* const drv, uint8_t reg, uint8_t val);
uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg); uint8_t si5351c_read_single(si5351c_driver_t* const drv, uint8_t reg);
void si5351c_write(si5351c_driver_t* const drv, const uint8_t* const data, const size_t data_count); void si5351c_write(
si5351c_driver_t* const drv,
const uint8_t* const data,
const size_t data_count);
void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable); void si5351c_clkout_enable(si5351c_driver_t* const drv, uint8_t enable);
#ifdef __cplusplus #ifdef __cplusplus

View File

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

View File

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

View File

@ -24,10 +24,11 @@
#include <libopencm3/lpc43xx/rgu.h> #include <libopencm3/lpc43xx/rgu.h>
#include <libopencm3/lpc43xx/ssp.h> #include <libopencm3/lpc43xx/ssp.h>
void spi_ssp_start(spi_bus_t* const bus, const void* const _config) { void spi_ssp_start(spi_bus_t* const bus, const void* const _config)
{
const ssp_config_t* const config = _config; const ssp_config_t* const config = _config;
if( bus->obj == (void*)SSP0_BASE ) { if (bus->obj == (void*) SSP0_BASE) {
/* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */ /* Reset SPIFI peripheral before to Erase/Write SPIFI memory through SPI */
RESET_CTRL1 = RESET_CTRL1_SPIFI_RST; 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_CR1(bus->obj) = 0;
SSP_CPSR(bus->obj) = config->clock_prescale_rate; SSP_CPSR(bus->obj) = config->clock_prescale_rate;
SSP_CR0(bus->obj) = SSP_CR0(bus->obj) = (config->serial_clock_rate << 8) | SSP_CPOL_0_CPHA_0 |
(config->serial_clock_rate << 8) SSP_FRAME_SPI | config->data_bits;
| SSP_CPOL_0_CPHA_0
| SSP_FRAME_SPI
| config->data_bits
;
SSP_CR1(bus->obj) = SSP_CR1(bus->obj) =
SSP_SLAVE_OUT_ENABLE SSP_SLAVE_OUT_ENABLE | SSP_MASTER | SSP_ENABLE | SSP_MODE_NORMAL;
| SSP_MASTER
| SSP_ENABLE
| SSP_MODE_NORMAL
;
bus->config = config; bus->config = config;
} }
void spi_ssp_stop(spi_bus_t* const bus) { void spi_ssp_stop(spi_bus_t* const bus)
{
SSP_CR1(bus->obj) = 0; SSP_CR1(bus->obj) = 0;
} }
static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus) { static void spi_ssp_wait_for_tx_fifo_not_full(spi_bus_t* const bus)
while( (SSP_SR(bus->obj) & SSP_SR_TNF) == 0 ) {} {
while ((SSP_SR(bus->obj) & SSP_SR_TNF) == 0) {}
} }
static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus) { static void spi_ssp_wait_for_rx_fifo_not_empty(spi_bus_t* const bus)
while( (SSP_SR(bus->obj) & SSP_SR_RNE) == 0 ) {} {
while ((SSP_SR(bus->obj) & SSP_SR_RNE) == 0) {}
} }
static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus) { static void spi_ssp_wait_for_not_busy(spi_bus_t* const bus)
while( SSP_SR(bus->obj) & SSP_SR_BSY ) {} {
while (SSP_SR(bus->obj) & SSP_SR_BSY) {}
} }
static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data) { static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data)
{
spi_ssp_wait_for_tx_fifo_not_full(bus); spi_ssp_wait_for_tx_fifo_not_full(bus);
SSP_DR(bus->obj) = data; SSP_DR(bus->obj) = data;
spi_ssp_wait_for_not_busy(bus); spi_ssp_wait_for_not_busy(bus);
@ -77,23 +75,27 @@ static uint32_t spi_ssp_transfer_word(spi_bus_t* const bus, const uint32_t data)
return SSP_DR(bus->obj); return SSP_DR(bus->obj);
} }
void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count) { void spi_ssp_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count)
{
const ssp_config_t* const config = bus->config; const ssp_config_t* const config = bus->config;
const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS; const bool word_size_u16 = (SSP_CR0(bus->obj) & 0xf) > SSP_DATA_8BITS;
gpio_clear(config->gpio_select); 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; const size_t data_count = transfers[i].count;
if( word_size_u16 ) { if (word_size_u16) {
uint16_t* const data = transfers[i].data; 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]); data[j] = spi_ssp_transfer_word(bus, data[j]);
} }
} else { } else {
uint8_t* const data = transfers[i].data; 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]); 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); gpio_set(config->gpio_select);
} }
void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count) { void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count)
{
const spi_transfer_t transfers[] = { const spi_transfer_t transfers[] = {
{ data, count }, {data, count},
}; };
spi_ssp_transfer_gather(bus, transfers, 1); 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_start(spi_bus_t* const bus, const void* const config);
void spi_ssp_stop(spi_bus_t* const bus); void spi_ssp_stop(spi_bus_t* const bus);
void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count); void spi_ssp_transfer(spi_bus_t* const bus, void* const data, const size_t count);
void spi_ssp_transfer_gather(spi_bus_t* const bus, const spi_transfer_t* const transfers, const size_t count); void spi_ssp_transfer_gather(
spi_bus_t* const bus,
const spi_transfer_t* const transfers,
const size_t count);
#endif/*__SPI_SSP_H__*/ #endif /*__SPI_SSP_H__*/

View File

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

View File

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

View File

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

View File

@ -26,4 +26,4 @@
const hackrf_ui_t* portapack_hackrf_ui_init() __attribute__((weak)); 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 transceiver_mode_t trx_mode;
static bool enabled = false; static bool enabled = false;
#define BLACK 0b00000000 #define BLACK 0b00000000
#define RED 0b11100000 #define RED 0b11100000
#define RED_DARK 0b01100000 #define RED_DARK 0b01100000
#define GREEN 0b00011100 #define GREEN 0b00011100
#define GREEN_DARK 0b00001100 #define GREEN_DARK 0b00001100
#define BLUE 0b00000011 #define BLUE 0b00000011
#define WHITE 0b11111111 #define WHITE 0b11111111
#define GREY 0b01001101 #define GREY 0b01001101
static void draw_frequency(void) static void draw_frequency(void)
{ {
@ -61,7 +61,7 @@ static void draw_frequency(void)
rad1o_setTextColor(BLACK, GREEN); rad1o_setTextColor(BLACK, GREEN);
rad1o_setIntFont(&Font_Ubuntu18pt); 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_lcdPrint(tmp);
rad1o_setIntFont(&Font_7x8); rad1o_setIntFont(&Font_7x8);
@ -148,7 +148,7 @@ static void ui_update(void)
rad1o_lcdPrint("Rate: "); rad1o_lcdPrint("Rate: ");
mhz = sample_rate / 1000000; mhz = sample_rate / 1000000;
khz = (sample_rate - mhz * 1000000) / 1000; 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_lcdPrint(tmp);
rad1o_lcdNl(); rad1o_lcdNl();
@ -156,7 +156,7 @@ static void ui_update(void)
rad1o_lcdPrint("Filter: "); rad1o_lcdPrint("Filter: ");
mhz = filter_bw / 1000000; mhz = filter_bw / 1000000;
khz = (filter_bw - mhz * 1000000) / 1000; 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_lcdPrint(tmp);
rad1o_lcdNl(); rad1o_lcdNl();
@ -181,7 +181,7 @@ static void ui_update(void)
if (direction == RF_PATH_DIRECTION_TX) { if (direction == RF_PATH_DIRECTION_TX) {
rad1o_setTextColor(BLACK, RED); 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_lcdPrint(tmp);
rad1o_lcdNl(); rad1o_lcdNl();
@ -190,11 +190,11 @@ static void ui_update(void)
if (direction == RF_PATH_DIRECTION_RX) { if (direction == RF_PATH_DIRECTION_RX) {
rad1o_setTextColor(BLACK, GREEN); 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_lcdPrint(tmp);
rad1o_lcdNl(); rad1o_lcdNl();
rad1o_lcdMoveCrsr(2, 0); 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_lcdPrint(tmp);
rad1o_lcdNl(); rad1o_lcdNl();
@ -277,8 +277,7 @@ static void rad1o_ui_set_first_if_frequency(const uint64_t frequency
// Not implemented // Not implemented
} }
static void rad1o_ui_set_filter(const rf_path_filter_t filter static void rad1o_ui_set_filter(const rf_path_filter_t filter __attribute__((unused)))
__attribute__((unused)))
{ {
// Not implemented // Not implemented
} }
@ -288,8 +287,7 @@ static void rad1o_ui_set_antenna_bias(bool antenna_bias __attribute__((unused)))
// Not implemented // Not implemented
} }
static void rad1o_ui_set_clock_source(clock_source_t source static void rad1o_ui_set_clock_source(clock_source_t source __attribute__((unused)))
__attribute__((unused)))
{ {
// Not implemented // Not implemented
} }
@ -324,7 +322,7 @@ static const hackrf_ui_t rad1o_ui = {
&rad1o_ui_operacake_gpio_compatible, &rad1o_ui_operacake_gpio_compatible,
}; };
const hackrf_ui_t *rad1o_ui_setup(void) const hackrf_ui_t* rad1o_ui_setup(void)
{ {
return &rad1o_ui; return &rad1o_ui;
} }

View File

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

View File

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

View File

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

View File

@ -25,70 +25,64 @@
#include <stdbool.h> #include <stdbool.h>
static void usb_request( static void usb_request(usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage)
usb_endpoint_t* const endpoint, {
const usb_transfer_stage_t stage
) {
usb_request_status_t status = USB_REQUEST_STATUS_STALL; usb_request_status_t status = USB_REQUEST_STATUS_STALL;
usb_request_handler_fn handler = 0; usb_request_handler_fn handler = 0;
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: case USB_SETUP_REQUEST_TYPE_STANDARD:
handler = usb_request_handlers.standard; handler = usb_request_handlers.standard;
break; break;
case USB_SETUP_REQUEST_TYPE_CLASS: case USB_SETUP_REQUEST_TYPE_CLASS:
handler = usb_request_handlers.class; handler = usb_request_handlers.class;
break; break;
case USB_SETUP_REQUEST_TYPE_VENDOR: case USB_SETUP_REQUEST_TYPE_VENDOR:
handler = usb_request_handlers.vendor; handler = usb_request_handlers.vendor;
break; break;
case USB_SETUP_REQUEST_TYPE_RESERVED: case USB_SETUP_REQUEST_TYPE_RESERVED:
handler = usb_request_handlers.reserved; handler = usb_request_handlers.reserved;
break; break;
} }
if( handler ) { if (handler) {
status = handler(endpoint, stage); 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 2.0 section 9.2.7 "Request Error"
usb_endpoint_stall(endpoint); usb_endpoint_stall(endpoint);
} }
} }
void usb_setup_complete( void usb_setup_complete(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) {
usb_request(endpoint, USB_TRANSFER_STAGE_SETUP); usb_request(endpoint, USB_TRANSFER_STAGE_SETUP);
} }
void usb_control_out_complete( void usb_control_out_complete(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) { const bool device_to_host = endpoint->setup.request_type >>
const bool device_to_host = USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift; if (device_to_host) {
if( device_to_host ) {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS); usb_request(endpoint, USB_TRANSFER_STAGE_STATUS);
} else { } else {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA); usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
} }
usb_queue_transfer_complete(endpoint); usb_queue_transfer_complete(endpoint);
} }
void usb_control_in_complete( void usb_control_in_complete(usb_endpoint_t* const endpoint)
usb_endpoint_t* const endpoint {
) { const bool device_to_host = endpoint->setup.request_type >>
const bool device_to_host = USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift;
endpoint->setup.request_type >> USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift; if (device_to_host) {
if( device_to_host ) {
usb_request(endpoint, USB_TRANSFER_STAGE_DATA); usb_request(endpoint, USB_TRANSFER_STAGE_DATA);
} else { } else {
usb_request(endpoint, USB_TRANSFER_STAGE_STATUS); 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_OK = 0,
USB_REQUEST_STATUS_STALL = 1, USB_REQUEST_STATUS_STALL = 1,
} usb_request_status_t; } usb_request_status_t;
typedef usb_request_status_t (*usb_request_handler_fn)( typedef usb_request_status_t (*usb_request_handler_fn)(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage);
);
typedef struct { typedef struct {
usb_request_handler_fn standard; usb_request_handler_fn standard;
@ -56,16 +55,10 @@ typedef struct {
extern const usb_request_handlers_t usb_request_handlers; extern const usb_request_handlers_t usb_request_handlers;
void usb_setup_complete( void usb_setup_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
void usb_control_in_complete( void usb_control_in_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
void usb_control_out_complete( void usb_control_out_complete(usb_endpoint_t* const endpoint);
usb_endpoint_t* const endpoint
);
#endif//__USB_REQUEST_H__ #endif //__USB_REQUEST_H__

View File

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

View File

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

View File

@ -26,32 +26,38 @@
#include <stdbool.h> #include <stdbool.h>
// TODO: Move this to some common compiler-tricks location. // TODO: Move this to some common compiler-tricks location.
#define ATTR_PACKED __attribute__((packed)) #define ATTR_PACKED __attribute__((packed))
#define ATTR_ALIGNED(x) __attribute__ ((aligned(x))) #define ATTR_ALIGNED(x) __attribute__((aligned(x)))
#define ATTR_SECTION(x) __attribute__ ((section(x))) #define ATTR_SECTION(x) __attribute__((section(x)))
typedef struct ATTR_PACKED { typedef struct ATTR_PACKED {
uint8_t request_type; uint8_t request_type;
uint8_t request; uint8_t request;
union { union {
struct { struct {
uint8_t value_l; uint8_t value_l;
uint8_t value_h; uint8_t value_h;
}; };
uint16_t value; uint16_t value;
}; };
union { union {
struct { struct {
uint8_t index_l; uint8_t index_l;
uint8_t index_h; uint8_t index_h;
}; };
uint16_t index; uint16_t index;
}; };
union { union {
struct { struct {
uint8_t length_l; uint8_t length_l;
uint8_t length_h; uint8_t length_h;
}; };
uint16_t length; uint16_t length;
}; };
} usb_setup_t; } usb_setup_t;
@ -77,23 +83,26 @@ typedef enum {
typedef enum { typedef enum {
USB_SETUP_REQUEST_TYPE_shift = 5, USB_SETUP_REQUEST_TYPE_shift = 5,
USB_SETUP_REQUEST_TYPE_mask = 3 << USB_SETUP_REQUEST_TYPE_shift, 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_STANDARD = 0 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_CLASS = 1 << 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_VENDOR = 2 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_RESERVED = 3 << USB_SETUP_REQUEST_TYPE_shift, USB_SETUP_REQUEST_TYPE_RESERVED = 3 << USB_SETUP_REQUEST_TYPE_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift = 7, USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift = 7,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_mask = 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift, USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_mask =
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_HOST_TO_DEVICE = 0 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift, 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_DEVICE_TO_HOST = 1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift, USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_HOST_TO_DEVICE =
0 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_DEVICE_TO_HOST =
1 << USB_SETUP_REQUEST_TYPE_DATA_TRANSFER_DIRECTION_shift,
} usb_setup_request_type_t; } usb_setup_request_type_t;
typedef enum { typedef enum {
USB_TRANSFER_DIRECTION_OUT = 0, USB_TRANSFER_DIRECTION_OUT = 0,
USB_TRANSFER_DIRECTION_IN = 1, USB_TRANSFER_DIRECTION_IN = 1,
} usb_transfer_direction_t; } usb_transfer_direction_t;
typedef enum { typedef enum {
USB_DESCRIPTOR_TYPE_DEVICE = 1, USB_DESCRIPTOR_TYPE_DEVICE = 1,
USB_DESCRIPTOR_TYPE_CONFIGURATION = 2, USB_DESCRIPTOR_TYPE_CONFIGURATION = 2,
@ -137,9 +146,10 @@ typedef struct {
} usb_device_t; } usb_device_t;
typedef struct usb_endpoint_t usb_endpoint_t; typedef struct usb_endpoint_t usb_endpoint_t;
struct usb_endpoint_t { struct usb_endpoint_t {
usb_setup_t setup; usb_setup_t setup;
uint8_t buffer[8]; // Buffer for use during IN stage. uint8_t buffer[8]; // Buffer for use during IN stage.
const uint_fast8_t address; const uint_fast8_t address;
usb_device_t* const device; usb_device_t* const device;
usb_endpoint_t* const in; usb_endpoint_t* const in;
@ -148,4 +158,4 @@ struct usb_endpoint_t {
void (*transfer_complete)(usb_endpoint_t* const endpoint); 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_DEVICE_ID 0xAB
#define W25Q80BV_UNIQUE_ID 0x4B #define W25Q80BV_UNIQUE_ID 0x4B
#define W25Q80BV_STATUS_BUSY 0x01 #define W25Q80BV_STATUS_BUSY 0x01
#define W25Q80BV_STATUS_WEL 0x02 #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. * 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 { do {
device_id = w25q80bv_get_device_id(drv); device_id = w25q80bv_get_device_id(drv);
} while(device_id != W25Q80BV_DEVICE_ID_RES && } while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES); device_id != W25Q16DV_DEVICE_ID_RES);
} }
uint8_t w25q80bv_get_status(w25q80bv_driver_t* const drv) 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)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
return data[1]; 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 w25q80bv_get_device_id(w25q80bv_driver_t* const drv)
{ {
uint8_t data[] = { uint8_t data[] = {W25Q80BV_DEVICE_ID, 0xFF, 0xFF, 0xFF, 0xFF};
W25Q80BV_DEVICE_ID,
0xFF, 0xFF, 0xFF, 0xFF
};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
return data[4]; return data[4];
} }
@ -92,13 +89,22 @@ void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t*
{ {
uint8_t data[] = { uint8_t data[] = {
W25Q80BV_UNIQUE_ID, W25Q80BV_UNIQUE_ID,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF 0xFF,
}; 0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF};
spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
for(size_t i=0; i<8; i++) { for (size_t i = 0; i < 8; i++) {
unique_id->id_8b[i] = data[5+i]; unique_id->id_8b[i] = data[5 + i];
} }
} }
@ -111,7 +117,7 @@ void w25q80bv_write_enable(w25q80bv_driver_t* const drv)
{ {
w25q80bv_wait_while_busy(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)); 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)) {}
} }
@ -122,18 +128,22 @@ void w25q80bv_chip_erase(w25q80bv_driver_t* const drv)
do { do {
device_id = w25q80bv_get_device_id(drv); device_id = w25q80bv_get_device_id(drv);
} while(device_id != W25Q80BV_DEVICE_ID_RES && } while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES); device_id != W25Q16DV_DEVICE_ID_RES);
w25q80bv_wait_while_busy(drv); w25q80bv_wait_while_busy(drv);
w25q80bv_write_enable(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)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
} }
/* write up a 256 byte page or partial page */ /* write up a 256 byte page or partial page */
static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t addr, const uint16_t len, uint8_t* data) static void w25q80bv_page_program(
w25q80bv_driver_t* const drv,
const uint32_t addr,
const uint16_t len,
uint8_t* data)
{ {
/* do nothing if asked to write beyond a page boundary */ /* do nothing if asked to write beyond a page boundary */
if (((addr & 0xFF) + len) > drv->page_len) if (((addr & 0xFF) + len) > drv->page_len)
@ -150,31 +160,31 @@ static void w25q80bv_page_program(w25q80bv_driver_t* const drv, const uint32_t a
W25Q80BV_PAGE_PROGRAM, W25Q80BV_PAGE_PROGRAM,
(addr & 0xFF0000) >> 16, (addr & 0xFF0000) >> 16,
(addr & 0xFF00) >> 8, (addr & 0xFF00) >> 8,
addr & 0xFF addr & 0xFF};
};
const spi_transfer_t transfers[] = { const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}};
{ header, ARRAY_SIZE(header) },
{ data, len }
};
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
} }
/* write an arbitrary number of bytes */ /* write an arbitrary number of bytes */
void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* data) void w25q80bv_program(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* data)
{ {
uint16_t first_block_len; uint16_t first_block_len;
uint8_t device_id; uint8_t device_id;
do { do {
device_id = w25q80bv_get_device_id(drv); device_id = w25q80bv_get_device_id(drv);
} while(device_id != W25Q80BV_DEVICE_ID_RES && } while (device_id != W25Q80BV_DEVICE_ID_RES &&
device_id != W25Q16DV_DEVICE_ID_RES); device_id != W25Q16DV_DEVICE_ID_RES);
/* do nothing if we would overflow the flash */ /* do nothing if we would overflow the flash */
if ((len > drv->num_bytes) || (addr > drv->num_bytes) if ((len > drv->num_bytes) || (addr > drv->num_bytes) ||
|| ((addr + len) > drv->num_bytes)) ((addr + len) > drv->num_bytes))
return; return;
/* handle start not at page boundary */ /* handle start not at page boundary */
@ -203,11 +213,15 @@ void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len,
} }
/* write an arbitrary number of bytes */ /* write an arbitrary number of bytes */
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data) void w25q80bv_read(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* const data)
{ {
/* do nothing if we would overflow the flash */ /* do nothing if we would overflow the flash */
if ((len > drv->num_bytes) || (addr > drv->num_bytes) if ((len > drv->num_bytes) || (addr > drv->num_bytes) ||
|| ((addr + len) > drv->num_bytes)) ((addr + len) > drv->num_bytes))
return; return;
w25q80bv_wait_while_busy(drv); w25q80bv_wait_while_busy(drv);
@ -217,13 +231,9 @@ void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, ui
(addr & 0xFF0000) >> 16, (addr & 0xFF0000) >> 16,
(addr & 0xFF00) >> 8, (addr & 0xFF00) >> 8,
addr & 0xFF, addr & 0xFF,
0x00 0x00};
};
const spi_transfer_t transfers[] = { const spi_transfer_t transfers[] = {{header, ARRAY_SIZE(header)}, {data, len}};
{ header, ARRAY_SIZE(header) },
{ data, len }
};
spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers)); spi_bus_transfer_gather(drv->bus, transfers, ARRAY_SIZE(transfers));
} }
@ -232,16 +242,16 @@ void w25q80bv_clear_status(w25q80bv_driver_t* const drv)
{ {
w25q80bv_wait_while_busy(drv); w25q80bv_wait_while_busy(drv);
w25q80bv_write_enable(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)); spi_bus_transfer(drv->bus, data, ARRAY_SIZE(data));
} }
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data) void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data)
{ {
uint8_t cmd[] = { W25Q80BV_READ_STATUS1, 0xFF }; uint8_t cmd[] = {W25Q80BV_READ_STATUS1, 0xFF};
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd)); spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[0] = cmd[1]; data[0] = cmd[1];
cmd[0] =W25Q80BV_READ_STATUS2; cmd[0] = W25Q80BV_READ_STATUS2;
cmd[1] = 0xFF; cmd[1] = 0xFF;
spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd)); spi_bus_transfer(drv->bus, cmd, ARRAY_SIZE(cmd));
data[1] = cmd[1]; data[1] = cmd[1];

View File

@ -27,16 +27,15 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */ #define W25Q80BV_DEVICE_ID_RES 0x13 /* Expected device_id for W25Q80BV */
#define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */ #define W25Q16DV_DEVICE_ID_RES 0x14 /* Expected device_id for W25Q16DV */
#include "spi_bus.h" #include "spi_bus.h"
#include "gpio.h" #include "gpio.h"
typedef union typedef union {
{
uint64_t id_64b; uint64_t id_64b;
uint32_t id_32b[2]; /* 2*32bits 64bits Unique ID */ uint32_t id_32b[2]; /* 2*32bits 64bits Unique ID */
uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */ uint8_t id_8b[8]; /* 8*8bits 64bits Unique ID */
} w25q80bv_unique_id_t; } w25q80bv_unique_id_t;
struct w25q80bv_driver_t; struct w25q80bv_driver_t;
@ -55,10 +54,18 @@ struct w25q80bv_driver_t {
void w25q80bv_setup(w25q80bv_driver_t* const drv); void w25q80bv_setup(w25q80bv_driver_t* const drv);
void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data); void w25q80bv_get_full_status(w25q80bv_driver_t* const drv, uint8_t* data);
void w25q80bv_chip_erase(w25q80bv_driver_t* const drv); void w25q80bv_chip_erase(w25q80bv_driver_t* const drv);
void w25q80bv_program(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* data); void w25q80bv_program(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* data);
uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv); uint8_t w25q80bv_get_device_id(w25q80bv_driver_t* const drv);
void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id); void w25q80bv_get_unique_id(w25q80bv_driver_t* const drv, w25q80bv_unique_id_t* unique_id);
void w25q80bv_read(w25q80bv_driver_t* const drv, uint32_t addr, uint32_t len, uint8_t* const data); void w25q80bv_read(
w25q80bv_driver_t* const drv,
uint32_t addr,
uint32_t len,
uint8_t* const data);
void w25q80bv_clear_status(w25q80bv_driver_t* const drv); void w25q80bv_clear_status(w25q80bv_driver_t* const drv);
#endif//__W25Q80BV_H__ #endif //__W25Q80BV_H__

View File

@ -28,8 +28,9 @@
* automatically? * automatically?
*/ */
void w25q80bv_target_init(w25q80bv_driver_t* const drv) { void w25q80bv_target_init(w25q80bv_driver_t* const drv)
(void)drv; {
(void) drv;
/* Init SPIFI GPIO to Normal GPIO */ /* Init SPIFI GPIO to Normal GPIO */
@ -45,11 +46,11 @@ void w25q80bv_target_init(w25q80bv_driver_t* const drv) {
scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); scu_pinmux(P3_7, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4));
// P3_8 SPIFI SPIFI_CS => GPIO5[11] // P3_8 SPIFI SPIFI_CS => GPIO5[11]
scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4)); scu_pinmux(P3_8, (SCU_GPIO_FAST | SCU_CONF_FUNCTION4));
/* configure SSP pins */ /* configure SSP pins */
scu_pinmux(SCU_SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5)); scu_pinmux(SCU_SSP0_CIPO, (SCU_SSP_IO | SCU_CONF_FUNCTION5));
scu_pinmux(SCU_SSP0_COPI, (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 */ /* configure GPIO pins */
scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST); scu_pinmux(SCU_FLASH_HOLD, SCU_GPIO_FAST);

View File

@ -26,4 +26,4 @@
void w25q80bv_target_init(w25q80bv_driver_t* const drv); 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 "usb_api_m0_state.h"
#include "cpld_xc2c.h" #include "cpld_xc2c.h"
#include "portapack.h" #include "portapack.h"
#include "hackrf_ui.h" #include "hackrf_ui.h"
extern uint32_t __m0_start__; extern uint32_t __m0_start__;
@ -95,7 +95,7 @@ static usb_request_handler_fn vendor_request_handler[] = {
NULL, NULL,
#endif #endif
usb_vendor_request_set_freq_explicit, 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_init_sweep,
usb_vendor_request_operacake_get_boards, usb_vendor_request_operacake_get_boards,
usb_vendor_request_operacake_set_ports, 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_request_status_t usb_vendor_request(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
usb_request_status_t status = USB_REQUEST_STATUS_STALL; usb_request_status_t status = USB_REQUEST_STATUS_STALL;
if( endpoint->setup.request < vendor_request_handler_count ) { if (endpoint->setup.request < vendor_request_handler_count) {
usb_request_handler_fn handler = vendor_request_handler[endpoint->setup.request]; usb_request_handler_fn handler =
if( handler ) { vendor_request_handler[endpoint->setup.request];
if (handler) {
status = handler(endpoint, stage); status = handler(endpoint, stage);
} }
} }
return status; return status;
} }
@ -146,12 +147,11 @@ const usb_request_handlers_t usb_request_handlers = {
.reserved = 0, .reserved = 0,
}; };
void usb_configuration_changed( void usb_configuration_changed(usb_device_t* const device)
usb_device_t* const device {
) {
/* Reset transceiver to idle state until other commands are received */ /* Reset transceiver to idle state until other commands are received */
request_transceiver_mode(TRANSCEIVER_MODE_OFF); request_transceiver_mode(TRANSCEIVER_MODE_OFF);
if( device->configuration->number == 1 ) { if (device->configuration->number == 1) {
// transceiver configuration // transceiver configuration
led_on(LED1); led_on(LED1);
} else { } else {
@ -165,19 +165,24 @@ void usb_configuration_changed(
void usb_set_descriptor_by_serial_number(void) void usb_set_descriptor_by_serial_number(void)
{ {
iap_cmd_res_t iap_cmd_res; iap_cmd_res_t iap_cmd_res;
/* Read IAP Serial Number Identification */ /* Read IAP Serial Number Identification */
iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO; iap_cmd_res.cmd_param.command_code = IAP_CMD_READ_SERIAL_NO;
iap_cmd_call(&iap_cmd_res); iap_cmd_call(&iap_cmd_res);
if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) { if (iap_cmd_res.status_res.status_ret == CMD_SUCCESS) {
usb_descriptor_string_serial_number[0] = USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN; usb_descriptor_string_serial_number[0] =
USB_DESCRIPTOR_STRING_SERIAL_BUF_LEN;
usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING; usb_descriptor_string_serial_number[1] = USB_DESCRIPTOR_TYPE_STRING;
/* 32 characters of serial number, convert to UTF-16LE */ /* 32 characters of serial number, convert to UTF-16LE */
for (size_t i=0; i<USB_DESCRIPTOR_STRING_SERIAL_LEN; i++) { for (size_t i = 0; i < USB_DESCRIPTOR_STRING_SERIAL_LEN; i++) {
const uint_fast8_t nibble = (iap_cmd_res.status_res.iap_result[i >> 3] >> (28 - (i & 7) * 4)) & 0xf; const uint_fast8_t nibble =
const char c = (nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble); (iap_cmd_res.status_res.iap_result[i >> 3] >>
(28 - (i & 7) * 4)) &
0xf;
const char c =
(nibble > 9) ? ('a' + nibble - 10) : ('0' + nibble);
usb_descriptor_string_serial_number[2 + i * 2] = c; usb_descriptor_string_serial_number[2 + i * 2] = c;
usb_descriptor_string_serial_number[3 + i * 2] = 0x00; usb_descriptor_string_serial_number[3 + i * 2] = 0x00;
} }
@ -187,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_jtag_take(jtag);
cpld_xc2c64a_jtag_sram_write(jtag, &cpld_hackrf_program_sram); cpld_xc2c64a_jtag_sram_write(jtag, &cpld_hackrf_program_sram);
const bool success = cpld_xc2c64a_jtag_sram_verify(jtag, &cpld_hackrf_program_sram, &cpld_hackrf_verify); const bool success = cpld_xc2c64a_jtag_sram_verify(
jtag,
&cpld_hackrf_program_sram,
&cpld_hackrf_verify);
cpld_jtag_release(jtag); cpld_jtag_release(jtag);
return success; return success;
} }
static void m0_rom_to_ram() { static void m0_rom_to_ram()
uint32_t *dest = &__ram_m0_start__; {
uint32_t* dest = &__ram_m0_start__;
// Calculate the base address of ROM // Calculate the base address of ROM
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 // 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; uint32_t len = (uint32_t) &__m0_end__ - (uint32_t) src;
memcpy(dest, (uint32_t*)(base + src), len); memcpy(dest, (uint32_t*) (base + src), len);
} }
int main(void) { int main(void)
{
// Copy M0 image from ROM before SPIFI is disabled // Copy M0 image from ROM before SPIFI is disabled
m0_rom_to_ram(); m0_rom_to_ram();
@ -223,9 +234,9 @@ int main(void) {
cpu_clock_init(); cpu_clock_init();
/* Wake the M0 */ /* 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); halt_and_flash(6000000);
} }
@ -239,9 +250,9 @@ int main(void) {
usb_set_configuration_changed_cb(usb_configuration_changed); usb_set_configuration_changed_cb(usb_configuration_changed);
usb_peripheral_reset(); usb_peripheral_reset();
usb_device_init(0, &usb_device); usb_device_init(0, &usb_device);
usb_queue_init(&usb_endpoint_control_out_queue); usb_queue_init(&usb_endpoint_control_out_queue);
usb_queue_init(&usb_endpoint_control_in_queue); usb_queue_init(&usb_endpoint_control_in_queue);
usb_queue_init(&usb_endpoint_bulk_out_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_out);
usb_endpoint_init(&usb_endpoint_control_in); usb_endpoint_init(&usb_endpoint_control_in);
nvic_set_priority(NVIC_USB0_IRQ, 255); nvic_set_priority(NVIC_USB0_IRQ, 255);
hackrf_ui()->init(); hackrf_ui()->init();
usb_run(&usb_device); usb_run(&usb_device);
rf_path_init(&rf_path); rf_path_init(&rf_path);
bool operacake_allow_gpio; bool operacake_allow_gpio;
if( hackrf_ui()->operacake_gpio_compatible() ) { if (hackrf_ui()->operacake_gpio_compatible()) {
operacake_allow_gpio = true; operacake_allow_gpio = true;
} else { } else {
operacake_allow_gpio = false; operacake_allow_gpio = false;
} }
operacake_init(operacake_allow_gpio); operacake_init(operacake_allow_gpio);
while(true) { while (true) {
transceiver_request_t request; transceiver_request_t request;
// Briefly disable USB interrupt so that we can // Briefly disable USB interrupt so that we can

View File

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

View File

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

View File

@ -39,8 +39,8 @@ volatile bool cpld_wait = false;
static void cpld_buffer_refilled(void* user_data, unsigned int length) static void cpld_buffer_refilled(void* user_data, unsigned int length)
{ {
(void)user_data; (void) user_data;
(void)length; (void) length;
cpld_wait = false; cpld_wait = false;
} }
@ -52,8 +52,7 @@ static void refill_cpld_buffer(void)
cpld_xsvf_buffer, cpld_xsvf_buffer,
sizeof(cpld_xsvf_buffer), sizeof(cpld_xsvf_buffer),
cpld_buffer_refilled, cpld_buffer_refilled,
NULL NULL);
);
// Wait until transfer finishes // Wait until transfer finishes
while (cpld_wait) {} while (cpld_wait) {}
@ -68,14 +67,14 @@ void cpld_update(void)
refill_cpld_buffer(); refill_cpld_buffer();
error = cpld_jtag_program(&jtag_cpld, sizeof(cpld_xsvf_buffer), error = cpld_jtag_program(
cpld_xsvf_buffer, &jtag_cpld,
refill_cpld_buffer); sizeof(cpld_xsvf_buffer),
if(error == 0) cpld_xsvf_buffer,
{ refill_cpld_buffer);
if (error == 0) {
halt_and_flash(6000000); halt_and_flash(6000000);
}else } else {
{
/* LED3 (Red) steady on error */ /* LED3 (Red) steady on error */
led_on(LED3); led_on(LED3);
while (1) {} while (1) {}
@ -83,25 +82,32 @@ void cpld_update(void)
} }
usb_request_status_t usb_vendor_request_cpld_checksum( usb_request_status_t usb_vendor_request_cpld_checksum(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage) usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage)
{ {
static uint32_t cpld_crc; static uint32_t cpld_crc;
uint8_t length; uint8_t length;
if (stage == USB_TRANSFER_STAGE_SETUP) if (stage == USB_TRANSFER_STAGE_SETUP) {
{
cpld_jtag_take(&jtag_cpld); cpld_jtag_take(&jtag_cpld);
const bool checksum_success = cpld_xc2c64a_jtag_checksum(&jtag_cpld, &cpld_hackrf_verify, &cpld_crc); const bool checksum_success = cpld_xc2c64a_jtag_checksum(
&jtag_cpld,
&cpld_hackrf_verify,
&cpld_crc);
cpld_jtag_release(&jtag_cpld); cpld_jtag_release(&jtag_cpld);
if(!checksum_success) { if (!checksum_success) {
return USB_REQUEST_STATUS_STALL; return USB_REQUEST_STATUS_STALL;
} }
length = (uint8_t)sizeof(cpld_crc); length = (uint8_t) sizeof(cpld_crc);
memcpy(endpoint->buffer, &cpld_crc, length); memcpy(endpoint->buffer, &cpld_crc, length);
usb_transfer_schedule_block(endpoint->in, endpoint->buffer, length, usb_transfer_schedule_block(
NULL, NULL); endpoint->in,
endpoint->buffer,
length,
NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
} }
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;

View File

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

View File

@ -43,15 +43,15 @@ void m0_set_mode(enum m0_mode mode)
usb_request_status_t usb_vendor_request_get_m0_state( usb_request_status_t usb_vendor_request_get_m0_state(
usb_endpoint_t* const endpoint, usb_endpoint_t* const endpoint,
const usb_transfer_stage_t stage const usb_transfer_stage_t stage)
) { {
if( stage == USB_TRANSFER_STAGE_SETUP ) if (stage == USB_TRANSFER_STAGE_SETUP) {
{
usb_transfer_schedule_block( usb_transfer_schedule_block(
endpoint->in, endpoint->in,
(void*) &m0_state, (void*) &m0_state,
sizeof(m0_state), sizeof(m0_state),
NULL, NULL); NULL,
NULL);
usb_transfer_schedule_ack(endpoint->out); usb_transfer_schedule_ack(endpoint->out);
return USB_REQUEST_STATUS_OK; return USB_REQUEST_STATUS_OK;
} else { } else {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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