Merge pull request #1034 from schneider42/rad1o-ui-cleanup
rad1o UI support
This commit is contained in:
@ -43,6 +43,7 @@ void hackrf_ui_set_first_if_frequency_null(const uint64_t frequency) { UNUSED(fr
|
|||||||
void hackrf_ui_set_filter_null(const rf_path_filter_t filter) { UNUSED(filter); }
|
void hackrf_ui_set_filter_null(const rf_path_filter_t filter) { UNUSED(filter); }
|
||||||
void hackrf_ui_set_antenna_bias_null(bool antenna_bias) { UNUSED(antenna_bias); }
|
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); }
|
||||||
bool hackrf_ui_operacake_gpio_compatible_null(void) { return true; }
|
bool hackrf_ui_operacake_gpio_compatible_null(void) { return true; }
|
||||||
|
|
||||||
/* 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
|
||||||
@ -63,6 +64,7 @@ static const hackrf_ui_t hackrf_ui_null = {
|
|||||||
&hackrf_ui_set_filter_null,
|
&hackrf_ui_set_filter_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_operacake_gpio_compatible_null
|
&hackrf_ui_operacake_gpio_compatible_null
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ typedef void (*hackrf_ui_set_first_if_frequency_fn)(const uint64_t frequency);
|
|||||||
typedef void (*hackrf_ui_set_filter_fn)(const rf_path_filter_t filter);
|
typedef void (*hackrf_ui_set_filter_fn)(const rf_path_filter_t filter);
|
||||||
typedef void (*hackrf_ui_set_antenna_bias_fn)(bool antenna_bias);
|
typedef void (*hackrf_ui_set_antenna_bias_fn)(bool antenna_bias);
|
||||||
typedef void (*hackrf_ui_set_clock_source_fn)(clock_source_t source);
|
typedef void (*hackrf_ui_set_clock_source_fn)(clock_source_t source);
|
||||||
|
typedef void (*hackrf_ui_set_transceiver_mode_fn)(transceiver_mode_t mode);
|
||||||
typedef bool (*hackrf_ui_operacake_gpio_compatible_fn)(void);
|
typedef bool (*hackrf_ui_operacake_gpio_compatible_fn)(void);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -56,6 +57,7 @@ typedef struct {
|
|||||||
hackrf_ui_set_filter_fn set_filter;
|
hackrf_ui_set_filter_fn set_filter;
|
||||||
hackrf_ui_set_antenna_bias_fn set_antenna_bias;
|
hackrf_ui_set_antenna_bias_fn set_antenna_bias;
|
||||||
hackrf_ui_set_clock_source_fn set_clock_source;
|
hackrf_ui_set_clock_source_fn set_clock_source;
|
||||||
|
hackrf_ui_set_transceiver_mode_fn set_transceiver_mode;
|
||||||
hackrf_ui_operacake_gpio_compatible_fn operacake_gpio_compatible;
|
hackrf_ui_operacake_gpio_compatible_fn operacake_gpio_compatible;
|
||||||
} hackrf_ui_t;
|
} hackrf_ui_t;
|
||||||
|
|
||||||
|
127
firmware/common/rad1o/decoder.c
Normal file
127
firmware/common/rad1o/decoder.c
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#include "fonts.h"
|
||||||
|
#include "render.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Local function: Get next nibble.
|
||||||
|
static int ctr = 0; // offset for next nibble
|
||||||
|
static int hilo = 0; // 0= high nibble next, 1=low nibble next
|
||||||
|
static const uint8_t *data;
|
||||||
|
|
||||||
|
#define MAXCHR (30 * 20)
|
||||||
|
static uint8_t charBuf[MAXCHR];
|
||||||
|
|
||||||
|
// Get next nibble
|
||||||
|
static uint8_t gnn()
|
||||||
|
{
|
||||||
|
static uint8_t byte;
|
||||||
|
uint8_t val;
|
||||||
|
if (hilo == 1)
|
||||||
|
ctr++;
|
||||||
|
hilo = 1 - hilo;
|
||||||
|
if (hilo == 1) {
|
||||||
|
byte = data[ctr];
|
||||||
|
val = byte >> 4;
|
||||||
|
} else {
|
||||||
|
val = byte & 0x0f;
|
||||||
|
};
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local function: Unpack "long run".
|
||||||
|
static int upl(int off)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
while ((retval = gnn()) == 0) {
|
||||||
|
off++;
|
||||||
|
};
|
||||||
|
while (off-- > 0) {
|
||||||
|
retval = retval << 4;
|
||||||
|
retval += gnn();
|
||||||
|
};
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *rad1o_pk_decode(const uint8_t *ldata, int *len)
|
||||||
|
{
|
||||||
|
ctr = 0;
|
||||||
|
hilo = 0;
|
||||||
|
data = ldata;
|
||||||
|
int length = *len; // Length of character bytestream
|
||||||
|
int height; // Height of character in bytes
|
||||||
|
int hoff; // bit position for non-integer heights
|
||||||
|
uint8_t *bufptr = charBuf; // Output buffer for decoded character
|
||||||
|
|
||||||
|
height = (rad1o_getFontHeight() - 1) / 8 + 1;
|
||||||
|
hoff = rad1o_getFontHeight() % 8;
|
||||||
|
|
||||||
|
#define DYN (12) // Decoder parameter: Fixed value for now.
|
||||||
|
int repeat = 0; // Decoder internal: repeat colum?
|
||||||
|
int curbit = 0; // Decoder internal: current bit (1 or 0)
|
||||||
|
int pos = 0; // Decoder internal: current bit position (0..7)
|
||||||
|
int nyb; // Decoder internal: current nibble / value
|
||||||
|
|
||||||
|
if (data[ctr] >> 4 == 14) { // Char starts with 1-bits.
|
||||||
|
gnn();
|
||||||
|
curbit = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
while (ctr < length) { /* Iterate the whole input stream */
|
||||||
|
|
||||||
|
/* Get next encoded nibble and decode */
|
||||||
|
nyb = gnn();
|
||||||
|
|
||||||
|
if (nyb == 15) {
|
||||||
|
repeat++;
|
||||||
|
continue;
|
||||||
|
} else if (nyb == 14) {
|
||||||
|
nyb = upl(0);
|
||||||
|
nyb += 1;
|
||||||
|
repeat += nyb;
|
||||||
|
continue;
|
||||||
|
} else if (nyb > DYN) {
|
||||||
|
nyb = (16 * (nyb - DYN - 1)) + gnn() + DYN + 1;
|
||||||
|
} else if (nyb == 0) {
|
||||||
|
nyb = upl(1);
|
||||||
|
nyb += (16 * (13 - DYN) + DYN) - 16;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Generate & output bits */
|
||||||
|
|
||||||
|
while (nyb-- > 0) {
|
||||||
|
if (pos == 0) // Clear each byte before we start.
|
||||||
|
*bufptr = 0;
|
||||||
|
if (curbit == 1) {
|
||||||
|
*bufptr |= 1 << (7 - pos);
|
||||||
|
};
|
||||||
|
pos++;
|
||||||
|
if (((bufptr - charBuf) % height) == (height - 1) &&
|
||||||
|
(pos == hoff)) {
|
||||||
|
// Finish incomplete last byte per column
|
||||||
|
pos = 8;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (pos == 8) {
|
||||||
|
bufptr++;
|
||||||
|
if ((bufptr - charBuf) % height ==
|
||||||
|
0) { // End of column?
|
||||||
|
while (repeat > 0) {
|
||||||
|
for (int y = 0; y < height;
|
||||||
|
y++) {
|
||||||
|
bufptr[0] =
|
||||||
|
bufptr[-height];
|
||||||
|
bufptr++;
|
||||||
|
};
|
||||||
|
repeat--;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
pos = 0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
curbit = 1 - curbit;
|
||||||
|
};
|
||||||
|
|
||||||
|
*len = (bufptr - charBuf) / height; // return size of output buffer.
|
||||||
|
return charBuf;
|
||||||
|
}
|
8
firmware/common/rad1o/decoder.h
Normal file
8
firmware/common/rad1o/decoder.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef __RAD1O_DECODER_H__
|
||||||
|
#define __RAD1O_DECODER_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint8_t *rad1o_pk_decode(const uint8_t *data, int *len);
|
||||||
|
|
||||||
|
#endif
|
180
firmware/common/rad1o/display.c
Normal file
180
firmware/common/rad1o/display.c
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
#include "gpio_lpc.h"
|
||||||
|
#include "hackrf_core.h"
|
||||||
|
|
||||||
|
#include <libopencm3/lpc43xx/scu.h>
|
||||||
|
#include <libopencm3/lpc43xx/ssp.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void delayms(const uint32_t milliseconds)
|
||||||
|
{
|
||||||
|
/* NOTE: Naively assumes 204 MHz instruction cycle clock and five instructions per count */
|
||||||
|
delay(milliseconds * 40800);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct gpio_t gpio_lcd_cs = GPIO(4, 12); /* P9_0 */
|
||||||
|
static struct gpio_t gpio_lcd_bl_en = GPIO(0, 8); /* P1_1 */
|
||||||
|
static struct gpio_t gpio_lcd_reset = GPIO(5, 17); /* P9_4 */
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Utility routines to manage nokia display */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
static void rotate(void);
|
||||||
|
|
||||||
|
static uint8_t lcdBuffer[RESX * RESY];
|
||||||
|
|
||||||
|
static bool isTurned;
|
||||||
|
|
||||||
|
static void select()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The LCD requires 9-Bit frames
|
||||||
|
* Freq = PCLK / (CPSDVSR * [SCR+1])
|
||||||
|
* We want 120ns / bit -> 8.3 MHz.
|
||||||
|
* SPI1 BASE CLOCK is expected to be 204 MHz.
|
||||||
|
* 204 MHz / ( 12 * (1 + 1)) = 8.5 MHz
|
||||||
|
*
|
||||||
|
* Set CPSDVSR = 12
|
||||||
|
*/
|
||||||
|
uint8_t serial_clock_rate = 1;
|
||||||
|
uint8_t clock_prescale_rate = 12;
|
||||||
|
|
||||||
|
ssp_init(LCD_SSP, SSP_DATA_9BITS, SSP_FRAME_SPI, SSP_CPOL_0_CPHA_0,
|
||||||
|
serial_clock_rate, clock_prescale_rate, SSP_MODE_NORMAL,
|
||||||
|
SSP_MASTER, SSP_SLAVE_OUT_ENABLE);
|
||||||
|
|
||||||
|
gpio_clear(&gpio_lcd_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deselect()
|
||||||
|
{
|
||||||
|
gpio_set(&gpio_lcd_cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(uint8_t cd, uint8_t data)
|
||||||
|
{
|
||||||
|
uint16_t frame = 0x0;
|
||||||
|
|
||||||
|
frame = cd << 8;
|
||||||
|
frame |= data;
|
||||||
|
|
||||||
|
ssp_transfer(LCD_SSP, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdInit(void)
|
||||||
|
{
|
||||||
|
gpio_output(&gpio_lcd_bl_en);
|
||||||
|
gpio_output(&gpio_lcd_reset);
|
||||||
|
gpio_output(&gpio_lcd_cs);
|
||||||
|
|
||||||
|
/* prepare SPI */
|
||||||
|
SETUPpin(LCD_DI);
|
||||||
|
SETUPpin(LCD_SCK);
|
||||||
|
|
||||||
|
// Reset the display
|
||||||
|
gpio_clear(&gpio_lcd_reset);
|
||||||
|
delayms(100);
|
||||||
|
gpio_set(&gpio_lcd_reset);
|
||||||
|
delayms(100);
|
||||||
|
|
||||||
|
select();
|
||||||
|
|
||||||
|
/* The controller is a PCF8833 - documentation can be found online. */
|
||||||
|
static uint8_t initseq_d[] = {
|
||||||
|
0x11, // SLEEP_OUT (wake up)
|
||||||
|
0x3A, 2, // mode 8bpp (2= 8bpp, 3= 12bpp, 5= 16bpp)
|
||||||
|
0x36, 0b11000000, // my,mx,v,lao,rgb,x,x,x
|
||||||
|
0x25, 0x3a, // set contrast
|
||||||
|
0x29, // display on
|
||||||
|
0x03, // BSTRON (booster voltage)
|
||||||
|
0x2A, 1, RESX, 0x2B, 1, RESY
|
||||||
|
};
|
||||||
|
uint16_t initseq_c = ~(/* commands: 1, data: 0 */
|
||||||
|
(1 << 0) | (1 << 1) | (0 << 2) | (1 << 3) |
|
||||||
|
(0 << 4) | (1 << 5) | (0 << 6) | (1 << 7) |
|
||||||
|
(1 << 8) | (1 << 9) | (0 << 10) | (0 << 11) |
|
||||||
|
(1 << 12) | (0 << 13) | (0 << 14) | 0);
|
||||||
|
|
||||||
|
write(0, 0x01); /* most color displays need the pause */
|
||||||
|
delayms(10);
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < sizeof(initseq_d)) {
|
||||||
|
write(initseq_c & 1, initseq_d[i++]);
|
||||||
|
initseq_c = initseq_c >> 1;
|
||||||
|
}
|
||||||
|
deselect();
|
||||||
|
rad1o_lcdFill(0xff); /* Clear display buffer */
|
||||||
|
rotate();
|
||||||
|
|
||||||
|
gpio_set(&gpio_lcd_bl_en);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdDeInit(void)
|
||||||
|
{
|
||||||
|
gpio_clear(&gpio_lcd_bl_en);
|
||||||
|
rad1o_lcdFill(0xff);
|
||||||
|
rad1o_lcdDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdFill(uint8_t f)
|
||||||
|
{
|
||||||
|
memset(lcdBuffer, f, RESX * RESY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdSetPixel(uint8_t x, uint8_t y, uint8_t f)
|
||||||
|
{
|
||||||
|
if (x > RESX || y > RESY)
|
||||||
|
return;
|
||||||
|
lcdBuffer[y * RESX + x] = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t getPixel(uint8_t x, uint8_t y)
|
||||||
|
{
|
||||||
|
return lcdBuffer[y * RESX + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *rad1o_lcdGetBuffer(void)
|
||||||
|
{
|
||||||
|
return lcdBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdDisplay(void)
|
||||||
|
{
|
||||||
|
select();
|
||||||
|
|
||||||
|
uint16_t x, y;
|
||||||
|
|
||||||
|
/* set (back) to 8 bpp mode */
|
||||||
|
write(TYPE_CMD, 0x3a);
|
||||||
|
write(TYPE_DATA, 2);
|
||||||
|
|
||||||
|
write(TYPE_CMD, 0x2C); // memory write (RAMWR)
|
||||||
|
|
||||||
|
for (y = 0; y < RESY; y++) {
|
||||||
|
for (x = 0; x < RESX; x++) {
|
||||||
|
write(TYPE_DATA, getPixel(x, y));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
deselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rotate(void)
|
||||||
|
{
|
||||||
|
select();
|
||||||
|
write(TYPE_CMD, 0x36); // MDAC-Command
|
||||||
|
if (isTurned) {
|
||||||
|
write(TYPE_DATA, 0b01100000); // my,mx,v,lao,rgb,x,x,x
|
||||||
|
isTurned = true;
|
||||||
|
} else {
|
||||||
|
write(TYPE_DATA, 0b11000000); // my,mx,v,lao,rgb,x,x,x
|
||||||
|
isTurned = false;
|
||||||
|
}
|
||||||
|
deselect();
|
||||||
|
rad1o_lcdDisplay();
|
||||||
|
}
|
30
firmware/common/rad1o/display.h
Normal file
30
firmware/common/rad1o/display.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef __RAD1O_DISPLAY_H__
|
||||||
|
#define __RAD1O_DISPLAY_H__
|
||||||
|
|
||||||
|
#include <libopencm3/cm3/common.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define RESX 130
|
||||||
|
#define RESY 130
|
||||||
|
|
||||||
|
#define TYPE_CMD 0
|
||||||
|
#define TYPE_DATA 1
|
||||||
|
|
||||||
|
#define _PIN(pin, func, ...) pin
|
||||||
|
#define _FUNC(pin, func, ...) func
|
||||||
|
#define SETUPpin(args...) scu_pinmux(_PIN(args), _FUNC(args))
|
||||||
|
|
||||||
|
#define LCD_DI P1_4, SCU_CONF_FUNCTION5 | SCU_SSP_IO
|
||||||
|
#define LCD_SCK P1_19, SCU_CONF_FUNCTION1 | SCU_SSP_IO
|
||||||
|
|
||||||
|
#define LCD_SSP SSP1_NUM
|
||||||
|
|
||||||
|
void rad1o_lcdInit(void);
|
||||||
|
void rad1o_lcdDeInit(void);
|
||||||
|
void rad1o_lcdFill(uint8_t f);
|
||||||
|
void rad1o_lcdDisplay(void);
|
||||||
|
void rad1o_lcdSetPixel(uint8_t x, uint8_t y, uint8_t f);
|
||||||
|
uint8_t *rad1o_lcdGetBuffer(void);
|
||||||
|
|
||||||
|
#endif
|
30
firmware/common/rad1o/draw.c
Normal file
30
firmware/common/rad1o/draw.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "display.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SWAP(p1, p2) \
|
||||||
|
do { \
|
||||||
|
uint8_t SWAP = p1; \
|
||||||
|
p1 = p2; \
|
||||||
|
p2 = SWAP; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
void rad1o_drawHLine(uint8_t y, uint8_t x1, uint8_t x2, uint8_t color)
|
||||||
|
{
|
||||||
|
if (x1 > x2) {
|
||||||
|
SWAP(x1, x2);
|
||||||
|
}
|
||||||
|
for (uint8_t i = x1; i <= x2; ++i) {
|
||||||
|
rad1o_lcdSetPixel(i, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_drawVLine(uint8_t x, uint8_t y1, uint8_t y2, uint8_t color)
|
||||||
|
{
|
||||||
|
if (y1 > y2) {
|
||||||
|
SWAP(y1, y2);
|
||||||
|
}
|
||||||
|
for (uint8_t i = y1; i <= y2; ++i) {
|
||||||
|
rad1o_lcdSetPixel(x, i, color);
|
||||||
|
}
|
||||||
|
}
|
9
firmware/common/rad1o/draw.h
Normal file
9
firmware/common/rad1o/draw.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef __RAD1O_DRAW_H__
|
||||||
|
#define __RAD1O_DRAW_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void rad1o_drawHLine(uint8_t y, uint8_t x1, uint8_t x2, uint8_t color);
|
||||||
|
void rad1o_drawVLine(uint8_t x, uint8_t y1, uint8_t y2, uint8_t color);
|
||||||
|
|
||||||
|
#endif
|
35
firmware/common/rad1o/fonts.h
Normal file
35
firmware/common/rad1o/fonts.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef __RAD1O_FONTS_H__
|
||||||
|
#define __RAD1O_FONTS_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Partially based on original code for the KS0108 by Stephane Rey */
|
||||||
|
/* Based on code code by Kevin Townsend */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const uint8_t widthBits; // width, in bits (or pixels), of the character
|
||||||
|
} FONT_CHAR_INFO;
|
||||||
|
|
||||||
|
struct FONT_DEF {
|
||||||
|
uint8_t u8Width; /* Character width for storage */
|
||||||
|
uint8_t u8Height; /* Character height for storage */
|
||||||
|
uint8_t u8FirstChar; /* The first character available */
|
||||||
|
uint8_t u8LastChar; /* The last character available */
|
||||||
|
const uint8_t *au8FontTable; /* Font table start address in memory */
|
||||||
|
const FONT_CHAR_INFO *charInfo; /* Pointer to array of char information */
|
||||||
|
const uint16_t *charExtra; /* Pointer to array of extra char info */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct EXTFONT {
|
||||||
|
uint8_t type; // 0: none, 1: static, 2: loaded
|
||||||
|
char name[13];
|
||||||
|
struct FONT_DEF def;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef const struct FONT_DEF *FONT;
|
||||||
|
|
||||||
|
#define FONT_DEFAULT 0
|
||||||
|
#define FONT_INTERNAL 1
|
||||||
|
#define FONT_EXTERNAL 2
|
||||||
|
|
||||||
|
#endif
|
43
firmware/common/rad1o/print.c
Normal file
43
firmware/common/rad1o/print.c
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include "print.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "fonts.h"
|
||||||
|
#include "render.h"
|
||||||
|
#include "smallfonts.h"
|
||||||
|
|
||||||
|
static int32_t x = 0;
|
||||||
|
static int32_t y = 0;
|
||||||
|
|
||||||
|
void rad1o_lcdPrint(const char *string)
|
||||||
|
{
|
||||||
|
x = rad1o_DoString(x, y, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdNl(void)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y += rad1o_getFontHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdClear(void)
|
||||||
|
{
|
||||||
|
x = 0;
|
||||||
|
y = 0;
|
||||||
|
rad1o_lcdFill(0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdMoveCrsr(int32_t dx, int32_t dy)
|
||||||
|
{
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_lcdSetCrsr(int32_t dx, int32_t dy)
|
||||||
|
{
|
||||||
|
x = dx;
|
||||||
|
y = dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_setSystemFont(void)
|
||||||
|
{
|
||||||
|
rad1o_setIntFont(&Font_7x8);
|
||||||
|
}
|
13
firmware/common/rad1o/print.h
Normal file
13
firmware/common/rad1o/print.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef __RAD1O_PRINT_H__
|
||||||
|
#define __RAD1O_PRINT_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void rad1o_lcdPrint(const char *string);
|
||||||
|
void rad1o_lcdNl(void);
|
||||||
|
void rad1o_lcdClear(void);
|
||||||
|
void rad1o_lcdMoveCrsr(int32_t dx, int32_t dy);
|
||||||
|
void rad1o_lcdSetCrsr(int32_t dx, int32_t dy);
|
||||||
|
void rad1o_setSystemFont(void);
|
||||||
|
|
||||||
|
#endif
|
162
firmware/common/rad1o/render.c
Normal file
162
firmware/common/rad1o/render.c
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
#include "render.h"
|
||||||
|
#include "decoder.h"
|
||||||
|
#include "display.h"
|
||||||
|
#include "fonts.h"
|
||||||
|
#include "smallfonts.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Global Variables */
|
||||||
|
static const struct FONT_DEF *font = NULL;
|
||||||
|
|
||||||
|
static struct EXTFONT efont;
|
||||||
|
|
||||||
|
static uint8_t color_bg = 0xff; /* background color */
|
||||||
|
static uint8_t color_fg = 0x00; /* foreground color */
|
||||||
|
|
||||||
|
/* Exported Functions */
|
||||||
|
void rad1o_setTextColor(uint8_t bg, uint8_t fg)
|
||||||
|
{
|
||||||
|
color_bg = bg;
|
||||||
|
color_fg = fg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rad1o_setIntFont(const struct FONT_DEF *newfont)
|
||||||
|
{
|
||||||
|
memcpy(&efont.def, newfont, sizeof(struct FONT_DEF));
|
||||||
|
efont.type = FONT_INTERNAL;
|
||||||
|
font = &efont.def;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rad1o_getFontHeight(void)
|
||||||
|
{
|
||||||
|
if (font)
|
||||||
|
return font->u8Height;
|
||||||
|
return 8; // XXX: Should be done right.
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _getIndex(int c)
|
||||||
|
{
|
||||||
|
#define ERRCHR (font->u8FirstChar + 1)
|
||||||
|
/* Does this font provide this character? */
|
||||||
|
if (c < font->u8FirstChar)
|
||||||
|
c = ERRCHR;
|
||||||
|
if (c > font->u8LastChar && efont.type != FONT_EXTERNAL &&
|
||||||
|
font->charExtra == NULL)
|
||||||
|
c = ERRCHR;
|
||||||
|
|
||||||
|
if (c > font->u8LastChar &&
|
||||||
|
(efont.type == FONT_EXTERNAL || font->charExtra != NULL)) {
|
||||||
|
int cc = 0;
|
||||||
|
while (font->charExtra[cc] < c)
|
||||||
|
cc++;
|
||||||
|
if (font->charExtra[cc] > c)
|
||||||
|
c = ERRCHR;
|
||||||
|
else
|
||||||
|
c = font->u8LastChar + cc + 1;
|
||||||
|
};
|
||||||
|
c -= font->u8FirstChar;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rad1o_DoChar(int sx, int sy, int c)
|
||||||
|
{
|
||||||
|
if (font == NULL) {
|
||||||
|
font = &Font_7x8;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* how many bytes is it high? */
|
||||||
|
char height = (font->u8Height - 1) / 8 + 1;
|
||||||
|
char hoff = (8 - (font->u8Height % 8)) % 8;
|
||||||
|
|
||||||
|
const uint8_t *data;
|
||||||
|
int width, preblank = 0, postblank = 0;
|
||||||
|
do { /* Get Character data */
|
||||||
|
/* Get intex into character list */
|
||||||
|
c = _getIndex(c);
|
||||||
|
|
||||||
|
/* starting offset into character source data */
|
||||||
|
int toff = 0;
|
||||||
|
|
||||||
|
if (font->u8Width == 0) {
|
||||||
|
for (int y = 0; y < c; y++)
|
||||||
|
toff += font->charInfo[y].widthBits;
|
||||||
|
width = font->charInfo[c].widthBits;
|
||||||
|
|
||||||
|
toff *= height;
|
||||||
|
data = &font->au8FontTable[toff];
|
||||||
|
postblank = 1;
|
||||||
|
} else if (font->u8Width == 1) { // NEW CODE
|
||||||
|
// Find offset and length for our character
|
||||||
|
for (int y = 0; y < c; y++)
|
||||||
|
toff += font->charInfo[y].widthBits;
|
||||||
|
width = font->charInfo[c].widthBits;
|
||||||
|
if (font->au8FontTable[toff] >> 4 ==
|
||||||
|
15) { // It's a raw character!
|
||||||
|
preblank = font->au8FontTable[toff + 1];
|
||||||
|
postblank = font->au8FontTable[toff + 2];
|
||||||
|
data = &font->au8FontTable[toff + 3];
|
||||||
|
width = (width - 3 / height);
|
||||||
|
} else {
|
||||||
|
data = rad1o_pk_decode(
|
||||||
|
&font->au8FontTable[toff], &width);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
toff = (c)*font->u8Width * 1;
|
||||||
|
width = font->u8Width;
|
||||||
|
data = &font->au8FontTable[toff];
|
||||||
|
};
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define xy_(x, y) \
|
||||||
|
((x < 0 || y < 0 || x >= RESX || y >= RESY) ? 0 : (y)*RESX + (x))
|
||||||
|
#define gPx(x, y) (data[x * height + (height - y / 8 - 1)] & (1 << (y % 8)))
|
||||||
|
|
||||||
|
int x = 0;
|
||||||
|
|
||||||
|
/* Fonts may not be byte-aligned, shift up so the top matches */
|
||||||
|
sy -= hoff;
|
||||||
|
|
||||||
|
sx += preblank;
|
||||||
|
|
||||||
|
uint8_t *lcdBuffer = rad1o_lcdGetBuffer();
|
||||||
|
/* per line */
|
||||||
|
for (int y = hoff; y < height * 8; y++) {
|
||||||
|
if (sy + y >= RESY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Optional: empty space to the left */
|
||||||
|
for (int b = 1; b <= preblank; b++) {
|
||||||
|
if (sx >= RESX)
|
||||||
|
continue;
|
||||||
|
lcdBuffer[xy_(sx - b, sy + y)] = color_bg;
|
||||||
|
};
|
||||||
|
/* Render character */
|
||||||
|
for (x = 0; x < width; x++) {
|
||||||
|
if (sx + x >= RESX)
|
||||||
|
continue;
|
||||||
|
if (gPx(x, y)) {
|
||||||
|
lcdBuffer[xy_(sx + x, sy + y)] = color_fg;
|
||||||
|
} else {
|
||||||
|
lcdBuffer[xy_(sx + x, sy + y)] = color_bg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
/* Optional: empty space to the right */
|
||||||
|
for (int m = 0; m < postblank; m++) {
|
||||||
|
if (sx + x + m >= RESX)
|
||||||
|
continue;
|
||||||
|
lcdBuffer[xy_(sx + x + m, sy + y)] = color_bg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return sx + (width + postblank);
|
||||||
|
}
|
||||||
|
|
||||||
|
int rad1o_DoString(int sx, int sy, const char *s)
|
||||||
|
{
|
||||||
|
const char *c;
|
||||||
|
for (c = s; *c != 0; c++) {
|
||||||
|
sx = rad1o_DoChar(sx, sy, *c);
|
||||||
|
};
|
||||||
|
return sx;
|
||||||
|
}
|
11
firmware/common/rad1o/render.h
Normal file
11
firmware/common/rad1o/render.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef __RENDER_H_
|
||||||
|
#define __RENDER_H_
|
||||||
|
|
||||||
|
#include "fonts.h"
|
||||||
|
|
||||||
|
void rad1o_setTextColor(uint8_t bg, uint8_t fg);
|
||||||
|
void rad1o_setIntFont(const struct FONT_DEF *font);
|
||||||
|
int rad1o_getFontHeight(void);
|
||||||
|
int rad1o_DoString(int sx, int sy, const char *s);
|
||||||
|
int rad1o_DoChar(int sx, int sy, int c);
|
||||||
|
#endif
|
144
firmware/common/rad1o/smallfonts.c
Normal file
144
firmware/common/rad1o/smallfonts.c
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/* Partially based on original code for the KS0108 by Stephane Rey */
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file smallfonts.c
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
#include "smallfonts.h"
|
||||||
|
|
||||||
|
/* System 7x8 */
|
||||||
|
const uint8_t au8Font7x8[] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, //' '
|
||||||
|
0, 6, 95, 95, 6, 0, 0, //'!'
|
||||||
|
0, 7, 7, 0, 7, 7, 0, //'"'
|
||||||
|
20, 127, 127, 20, 127, 127, 20, //'#'
|
||||||
|
36, 46, 107, 107, 58, 18, 0, //'$'
|
||||||
|
70, 102, 48, 24, 12, 102, 98, //'%'
|
||||||
|
48, 122, 79, 93, 55, 122, 72, //'&'
|
||||||
|
4, 7, 3, 0, 0, 0, 0, //'''
|
||||||
|
0, 28, 62, 99, 65, 0, 0, //'('
|
||||||
|
0, 65, 99, 62, 28, 0, 0, //')'
|
||||||
|
8, 42, 62, 28, 28, 62, 42, //'*'
|
||||||
|
8, 8, 62, 62, 8, 8, 0, //'+'
|
||||||
|
0, 128, 224, 96, 0, 0, 0, //','
|
||||||
|
8, 8, 8, 8, 8, 8, 0, //'-'
|
||||||
|
0, 0, 96, 96, 0, 0, 0, //'.'
|
||||||
|
96, 48, 24, 12, 6, 3, 1, //'/'
|
||||||
|
62, 127, 113, 89, 77, 127, 62, //'0'
|
||||||
|
64, 66, 127, 127, 64, 64, 0, //'1'
|
||||||
|
98, 115, 89, 73, 111, 102, 0, //'2'
|
||||||
|
34, 99, 73, 73, 127, 54, 0, //'3'
|
||||||
|
24, 28, 22, 83, 127, 127, 80, //'4'
|
||||||
|
39, 103, 69, 69, 125, 57, 0, //'5'
|
||||||
|
60, 126, 75, 73, 121, 48, 0, //'6'
|
||||||
|
3, 3, 113, 121, 15, 7, 0, //'7'
|
||||||
|
54, 127, 73, 73, 127, 54, 0, //'8'
|
||||||
|
6, 79, 73, 105, 63, 30, 0, //'9'
|
||||||
|
0, 0, 102, 102, 0, 0, 0, //':'
|
||||||
|
0, 128, 230, 102, 0, 0, 0, //';'
|
||||||
|
8, 28, 54, 99, 65, 0, 0, //'<'
|
||||||
|
36, 36, 36, 36, 36, 36, 0, //'='
|
||||||
|
0, 65, 99, 54, 28, 8, 0, //'>'
|
||||||
|
2, 3, 81, 89, 15, 6, 0, //'?'
|
||||||
|
62, 127, 65, 93, 93, 31, 30, //'@'
|
||||||
|
124, 126, 19, 19, 126, 124, 0, //'A'
|
||||||
|
65, 127, 127, 73, 73, 127, 54, //'B'
|
||||||
|
28, 62, 99, 65, 65, 99, 34, //'C'
|
||||||
|
65, 127, 127, 65, 99, 62, 28, //'D'
|
||||||
|
65, 127, 127, 73, 93, 65, 99, //'E'
|
||||||
|
65, 127, 127, 73, 29, 1, 3, //'F'
|
||||||
|
28, 62, 99, 65, 81, 115, 114, //'G'
|
||||||
|
127, 127, 8, 8, 127, 127, 0, //'H'
|
||||||
|
0, 65, 127, 127, 65, 0, 0, //'I'
|
||||||
|
48, 112, 64, 65, 127, 63, 1, //'J'
|
||||||
|
65, 127, 127, 8, 28, 119, 99, //'K'
|
||||||
|
65, 127, 127, 65, 64, 96, 112, //'L'
|
||||||
|
127, 127, 14, 28, 14, 127, 127, //'M'
|
||||||
|
127, 127, 6, 12, 24, 127, 127, //'N'
|
||||||
|
28, 62, 99, 65, 99, 62, 28, //'O'
|
||||||
|
65, 127, 127, 73, 9, 15, 6, //'P'
|
||||||
|
30, 63, 33, 113, 127, 94, 0, //'Q'
|
||||||
|
65, 127, 127, 9, 25, 127, 102, //'R'
|
||||||
|
38, 111, 77, 89, 115, 50, 0, //'S'
|
||||||
|
3, 65, 127, 127, 65, 3, 0, //'T'
|
||||||
|
127, 127, 64, 64, 127, 127, 0, //'U'
|
||||||
|
31, 63, 96, 96, 63, 31, 0, //'V'
|
||||||
|
127, 127, 48, 24, 48, 127, 127, //'W'
|
||||||
|
67, 103, 60, 24, 60, 103, 67, //'X'
|
||||||
|
7, 79, 120, 120, 79, 7, 0, //'Y'
|
||||||
|
71, 99, 113, 89, 77, 103, 115, //'Z'
|
||||||
|
0, 127, 127, 65, 65, 0, 0, //'['
|
||||||
|
1, 3, 6, 12, 24, 48, 96, //'\'
|
||||||
|
0, 65, 65, 127, 127, 0, 0, //']'
|
||||||
|
8, 12, 6, 3, 6, 12, 8, //'^'
|
||||||
|
128, 128, 128, 128, 128, 128, 128, //'_'
|
||||||
|
0, 0, 3, 7, 4, 0, 0, //'`'
|
||||||
|
32, 116, 84, 84, 60, 120, 64, //'a'
|
||||||
|
65, 127, 63, 72, 72, 120, 48, //'b'
|
||||||
|
56, 124, 68, 68, 108, 40, 0, //'c'
|
||||||
|
48, 120, 72, 73, 63, 127, 64, //'d'
|
||||||
|
56, 124, 84, 84, 92, 24, 0, //'e'
|
||||||
|
72, 126, 127, 73, 3, 2, 0, //'f'
|
||||||
|
56, 188, 164, 164, 252, 120, 0, //'g'
|
||||||
|
65, 127, 127, 8, 4, 124, 120, //'h'
|
||||||
|
0, 68, 125, 125, 64, 0, 0, //'i'
|
||||||
|
96, 224, 128, 128, 253, 125, 0, //'j'
|
||||||
|
65, 127, 127, 16, 56, 108, 68, //'k'
|
||||||
|
0, 65, 127, 127, 64, 0, 0, //'l'
|
||||||
|
120, 124, 28, 56, 28, 124, 120, //'m'
|
||||||
|
124, 124, 4, 4, 124, 120, 0, //'n'
|
||||||
|
56, 124, 68, 68, 124, 56, 0, //'o'
|
||||||
|
0, 252, 252, 164, 36, 60, 24, //'p'
|
||||||
|
24, 60, 36, 164, 248, 252, 132, //'q'
|
||||||
|
68, 124, 120, 76, 4, 28, 24, //'r'
|
||||||
|
72, 92, 84, 84, 116, 36, 0, //'s'
|
||||||
|
0, 4, 62, 127, 68, 36, 0, //'t'
|
||||||
|
60, 124, 64, 64, 60, 124, 64, //'u'
|
||||||
|
28, 60, 96, 96, 60, 28, 0, //'v'
|
||||||
|
60, 124, 112, 56, 112, 124, 60, //'w'
|
||||||
|
68, 108, 56, 16, 56, 108, 68, //'x'
|
||||||
|
60, 188, 160, 160, 252, 124, 0, //'y'
|
||||||
|
76, 100, 116, 92, 76, 100, 0, //'z'
|
||||||
|
8, 8, 62, 119, 65, 65, 0, //'{'
|
||||||
|
0, 0, 0, 119, 119, 0, 0, //'|'
|
||||||
|
65, 65, 119, 62, 8, 8, 0, //'}'
|
||||||
|
2, 3, 1, 3, 2, 3, 1, //'~'
|
||||||
|
255, 129, 129, 129, 129, 129, 255, //'^?'
|
||||||
|
14, 159, 145, 177, 251, 74, 0 //'?'
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Global variables */
|
||||||
|
const struct FONT_DEF Font_7x8 = { 7, 8, 32, 128, au8Font7x8, NULL, NULL };
|
51
firmware/common/rad1o/smallfonts.h
Normal file
51
firmware/common/rad1o/smallfonts.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@file smallfonts.h
|
||||||
|
@author K. Townsend (microBuilder.eu)
|
||||||
|
@date 22 March 2010
|
||||||
|
@version 0.10
|
||||||
|
|
||||||
|
@section LICENSE
|
||||||
|
|
||||||
|
Software License Agreement (BSD License)
|
||||||
|
|
||||||
|
Copyright (c) 2010, microBuilder SARL
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
3. Neither the name of the copyright holders nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||||
|
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||||
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
#ifndef __RAD1O_SMALLFONTS_H__
|
||||||
|
#define __RAD1O_SMALLFONTS_H__
|
||||||
|
|
||||||
|
#include "fonts.h"
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* Partially based on original code for the KS0108 by Stephane Rey */
|
||||||
|
/* Current version by Kevin Townsend */
|
||||||
|
|
||||||
|
extern const struct FONT_DEF Font_7x8;
|
||||||
|
|
||||||
|
#endif
|
3419
firmware/common/rad1o/ubuntu18.c
Normal file
3419
firmware/common/rad1o/ubuntu18.c
Normal file
File diff suppressed because it is too large
Load Diff
7
firmware/common/rad1o/ubuntu18.h
Normal file
7
firmware/common/rad1o/ubuntu18.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef __RAD1O_UBUNTU18_H__
|
||||||
|
#define __RAD1O_UBUNTU18_H__
|
||||||
|
#include "fonts.h"
|
||||||
|
|
||||||
|
extern const struct FONT_DEF Font_Ubuntu18pt;
|
||||||
|
|
||||||
|
#endif
|
@ -554,6 +554,10 @@ static void portapack_ui_set_clock_source(clock_source_t source) {
|
|||||||
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) {
|
||||||
|
(void)mode;
|
||||||
|
}
|
||||||
|
|
||||||
static bool portapack_ui_operacake_gpio_compatible(void) {
|
static bool portapack_ui_operacake_gpio_compatible(void) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -573,6 +577,7 @@ const hackrf_ui_t portapack_hackrf_ui = {
|
|||||||
&portapack_ui_set_filter,
|
&portapack_ui_set_filter,
|
||||||
&portapack_ui_set_antenna_bias,
|
&portapack_ui_set_antenna_bias,
|
||||||
&portapack_ui_set_clock_source,
|
&portapack_ui_set_clock_source,
|
||||||
|
&portapack_ui_set_transceiver_mode,
|
||||||
&portapack_ui_operacake_gpio_compatible,
|
&portapack_ui_operacake_gpio_compatible,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,78 +21,287 @@
|
|||||||
|
|
||||||
#include "ui_rad1o.h"
|
#include "ui_rad1o.h"
|
||||||
|
|
||||||
/* Weak functions from rad1o app */
|
#include "rad1o/display.h"
|
||||||
void hackrf_ui_init(void) __attribute__((weak));
|
#include "rad1o/draw.h"
|
||||||
void hackrf_ui_setFrequency(uint64_t _freq) __attribute__((weak));
|
#include "rad1o/print.h"
|
||||||
void hackrf_ui_setSampleRate(uint32_t _sample_rate) __attribute__((weak));
|
#include "rad1o/render.h"
|
||||||
void hackrf_ui_setDirection(const rf_path_direction_t _direction) __attribute__((weak));
|
#include "rad1o/smallfonts.h"
|
||||||
void hackrf_ui_setFilterBW(uint32_t bw) __attribute__((weak));
|
#include "rad1o/ubuntu18.h"
|
||||||
void hackrf_ui_setLNAPower(bool _lna_on) __attribute__((weak));
|
|
||||||
void hackrf_ui_setBBLNAGain(const uint32_t gain_db) __attribute__((weak));
|
|
||||||
void hackrf_ui_setBBVGAGain(const uint32_t gain_db) __attribute__((weak));
|
|
||||||
void hackrf_ui_setBBTXVGAGain(const uint32_t gain_db) __attribute__((weak));
|
|
||||||
void hackrf_ui_setFirstIFFrequency(const uint64_t freq) __attribute__((weak));
|
|
||||||
void hackrf_ui_setFilter(const rf_path_filter_t filter) __attribute__((weak));
|
|
||||||
void hackrf_ui_setAntennaBias(bool antenna_bias) __attribute__((weak));
|
|
||||||
void hackrf_ui_setClockSource(clock_source_t source) __attribute__((weak));
|
|
||||||
|
|
||||||
static void rad1o_ui_init(void) {
|
#include <stdio.h>
|
||||||
hackrf_ui_init();
|
|
||||||
|
static uint64_t freq = 0;
|
||||||
|
static uint32_t sample_rate = 0;
|
||||||
|
static uint32_t filter_bw = 0;
|
||||||
|
static rf_path_direction_t direction;
|
||||||
|
static uint32_t bblna_gain = 0;
|
||||||
|
static uint32_t bbvga_gain = 0;
|
||||||
|
static uint32_t bbtxvga_gain = 0;
|
||||||
|
static bool lna_on = false;
|
||||||
|
static transceiver_mode_t trx_mode;
|
||||||
|
static bool enabled = false;
|
||||||
|
|
||||||
|
#define BLACK 0b00000000
|
||||||
|
#define RED 0b11100000
|
||||||
|
#define RED_DARK 0b01100000
|
||||||
|
#define GREEN 0b00011100
|
||||||
|
#define GREEN_DARK 0b00001100
|
||||||
|
#define BLUE 0b00000011
|
||||||
|
#define WHITE 0b11111111
|
||||||
|
#define GREY 0b01001101
|
||||||
|
|
||||||
|
static void draw_frequency(void)
|
||||||
|
{
|
||||||
|
char tmp[100];
|
||||||
|
uint32_t mhz;
|
||||||
|
uint32_t khz;
|
||||||
|
|
||||||
|
mhz = freq / 1000000;
|
||||||
|
khz = (freq - mhz * 1000000) / 1000;
|
||||||
|
|
||||||
|
rad1o_setTextColor(BLACK, GREEN);
|
||||||
|
rad1o_setIntFont(&Font_Ubuntu18pt);
|
||||||
|
sprintf(tmp, "%4u.%03u", (unsigned int)mhz, (unsigned int)khz);
|
||||||
|
rad1o_lcdPrint(tmp);
|
||||||
|
|
||||||
|
rad1o_setIntFont(&Font_7x8);
|
||||||
|
rad1o_lcdMoveCrsr(1, 18 - 7);
|
||||||
|
rad1o_lcdPrint("MHz");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_deinit(void) {
|
static void draw_tx_rx(void)
|
||||||
|
{
|
||||||
|
uint8_t bg, fg;
|
||||||
|
|
||||||
|
rad1o_setIntFont(&Font_Ubuntu18pt);
|
||||||
|
|
||||||
|
bg = BLACK;
|
||||||
|
|
||||||
|
fg = GREY;
|
||||||
|
if (direction == RF_PATH_DIRECTION_OFF) {
|
||||||
|
fg = WHITE;
|
||||||
|
}
|
||||||
|
rad1o_setTextColor(bg, fg);
|
||||||
|
rad1o_lcdPrint("OFF ");
|
||||||
|
|
||||||
|
fg = GREY;
|
||||||
|
if (direction == RF_PATH_DIRECTION_RX) {
|
||||||
|
fg = GREEN;
|
||||||
|
}
|
||||||
|
rad1o_setTextColor(bg, fg);
|
||||||
|
rad1o_lcdPrint("RX ");
|
||||||
|
|
||||||
|
fg = GREY;
|
||||||
|
if (direction == RF_PATH_DIRECTION_TX) {
|
||||||
|
fg = RED;
|
||||||
|
}
|
||||||
|
rad1o_setTextColor(bg, fg);
|
||||||
|
rad1o_lcdPrint("TX");
|
||||||
|
|
||||||
|
rad1o_setIntFont(&Font_7x8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_frequency(uint64_t frequency) {
|
static void ui_update(void)
|
||||||
hackrf_ui_setFrequency(frequency);
|
{
|
||||||
|
char tmp[100];
|
||||||
|
uint32_t mhz;
|
||||||
|
uint32_t khz;
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_sample_rate(uint32_t sample_rate) {
|
rad1o_lcdClear();
|
||||||
hackrf_ui_setSampleRate(sample_rate);
|
rad1o_lcdFill(0x00);
|
||||||
|
|
||||||
|
rad1o_drawHLine(0, 0, RESX - 1, WHITE);
|
||||||
|
rad1o_drawVLine(0, 0, RESY - 1, WHITE);
|
||||||
|
|
||||||
|
rad1o_drawHLine(RESY - 1, 0, RESX - 1, WHITE);
|
||||||
|
rad1o_drawVLine(RESX - 1, 0, RESY - 1, WHITE);
|
||||||
|
|
||||||
|
rad1o_lcdSetCrsr(25, 2);
|
||||||
|
|
||||||
|
rad1o_setTextColor(BLACK, GREEN);
|
||||||
|
|
||||||
|
rad1o_lcdPrint("HackRF Mode");
|
||||||
|
rad1o_lcdNl();
|
||||||
|
|
||||||
|
rad1o_drawHLine(11, 0, RESX - 1, WHITE);
|
||||||
|
|
||||||
|
rad1o_lcdSetCrsr(2, 12);
|
||||||
|
if (trx_mode == TRANSCEIVER_MODE_RX_SWEEP) {
|
||||||
|
rad1o_setIntFont(&Font_Ubuntu18pt);
|
||||||
|
rad1o_lcdPrint("SWEEP");
|
||||||
|
} else {
|
||||||
|
draw_frequency();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_direction(const rf_path_direction_t direction) {
|
rad1o_drawHLine(40, 0, RESX - 1, WHITE);
|
||||||
hackrf_ui_setDirection(direction);
|
|
||||||
|
rad1o_lcdSetCrsr(6, 41);
|
||||||
|
draw_tx_rx();
|
||||||
|
rad1o_drawHLine(69, 0, RESX - 1, WHITE);
|
||||||
|
|
||||||
|
rad1o_setTextColor(BLACK, WHITE);
|
||||||
|
rad1o_lcdSetCrsr(2, 71);
|
||||||
|
rad1o_lcdPrint("Rate: ");
|
||||||
|
mhz = sample_rate / 1000000;
|
||||||
|
khz = (sample_rate - mhz * 1000000) / 1000;
|
||||||
|
sprintf(tmp, "%2u.%03u MHz", (unsigned int)mhz, (unsigned int)khz);
|
||||||
|
rad1o_lcdPrint(tmp);
|
||||||
|
rad1o_lcdNl();
|
||||||
|
|
||||||
|
rad1o_lcdMoveCrsr(2, 0);
|
||||||
|
rad1o_lcdPrint("Filter: ");
|
||||||
|
mhz = filter_bw / 1000000;
|
||||||
|
khz = (filter_bw - mhz * 1000000) / 1000;
|
||||||
|
sprintf(tmp, "%2u.%03u MHz", (unsigned int)mhz, (unsigned int)khz);
|
||||||
|
rad1o_lcdPrint(tmp);
|
||||||
|
rad1o_lcdNl();
|
||||||
|
|
||||||
|
rad1o_drawHLine(88, 0, RESX - 1, WHITE);
|
||||||
|
|
||||||
|
rad1o_setTextColor(BLACK, WHITE);
|
||||||
|
rad1o_lcdSetCrsr(2, 90);
|
||||||
|
rad1o_lcdPrint(" Gains");
|
||||||
|
rad1o_lcdNl();
|
||||||
|
|
||||||
|
rad1o_setTextColor(BLACK, GREEN);
|
||||||
|
rad1o_lcdMoveCrsr(2, 2);
|
||||||
|
rad1o_lcdPrint("AMP: ");
|
||||||
|
if (lna_on) {
|
||||||
|
rad1o_setTextColor(BLACK, RED);
|
||||||
|
rad1o_lcdPrint("ON ");
|
||||||
|
} else {
|
||||||
|
rad1o_lcdPrint("OFF");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_filter_bw(uint32_t bandwidth) {
|
rad1o_setTextColor(BLACK, RED_DARK);
|
||||||
hackrf_ui_setFilterBW(bandwidth);
|
if (direction == RF_PATH_DIRECTION_TX) {
|
||||||
|
rad1o_setTextColor(BLACK, RED);
|
||||||
|
}
|
||||||
|
sprintf(tmp, " TX: %u dB", (unsigned int)bbtxvga_gain);
|
||||||
|
rad1o_lcdPrint(tmp);
|
||||||
|
rad1o_lcdNl();
|
||||||
|
|
||||||
|
rad1o_lcdMoveCrsr(2, 0);
|
||||||
|
rad1o_setTextColor(BLACK, GREEN_DARK);
|
||||||
|
if (direction == RF_PATH_DIRECTION_RX) {
|
||||||
|
rad1o_setTextColor(BLACK, GREEN);
|
||||||
|
}
|
||||||
|
sprintf(tmp, "LNA: %2u dB", (unsigned int)bblna_gain);
|
||||||
|
rad1o_lcdPrint(tmp);
|
||||||
|
rad1o_lcdNl();
|
||||||
|
rad1o_lcdMoveCrsr(2, 0);
|
||||||
|
sprintf(tmp, "VGA: %2u dB", (unsigned int)bbvga_gain);
|
||||||
|
rad1o_lcdPrint(tmp);
|
||||||
|
rad1o_lcdNl();
|
||||||
|
|
||||||
|
rad1o_lcdDisplay();
|
||||||
|
|
||||||
|
// Don't ask...
|
||||||
|
ssp1_set_mode_max2837();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_lna_power(bool lna_on) {
|
static void rad1o_ui_init(void)
|
||||||
hackrf_ui_setLNAPower(lna_on);
|
{
|
||||||
|
rad1o_lcdInit();
|
||||||
|
enabled = true;
|
||||||
|
ui_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_bb_lna_gain(const uint32_t gain_db) {
|
static void rad1o_ui_deinit(void)
|
||||||
hackrf_ui_setBBLNAGain(gain_db);
|
{
|
||||||
|
rad1o_lcdDeInit();
|
||||||
|
enabled = false;
|
||||||
|
// Don't ask...
|
||||||
|
ssp1_set_mode_max2837();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_bb_vga_gain(const uint32_t gain_db) {
|
static void rad1o_ui_set_frequency(uint64_t frequency)
|
||||||
hackrf_ui_setBBVGAGain(gain_db);
|
{
|
||||||
|
freq = frequency;
|
||||||
|
|
||||||
|
if (TRANSCEIVER_MODE_RX_SWEEP == trx_mode) {
|
||||||
|
} else {
|
||||||
|
ui_update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_bb_tx_vga_gain(const uint32_t gain_db) {
|
static void rad1o_ui_set_sample_rate(uint32_t _sample_rate)
|
||||||
hackrf_ui_setBBTXVGAGain(gain_db);
|
{
|
||||||
|
sample_rate = _sample_rate;
|
||||||
|
ui_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_first_if_frequency(const uint64_t frequency) {
|
static void rad1o_ui_set_direction(const rf_path_direction_t _direction)
|
||||||
hackrf_ui_setFirstIFFrequency(frequency);
|
{
|
||||||
|
direction = _direction;
|
||||||
|
ui_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_filter(const rf_path_filter_t filter) {
|
static void rad1o_ui_set_filter_bw(uint32_t bandwidth)
|
||||||
hackrf_ui_setFilter(filter);
|
{
|
||||||
|
filter_bw = bandwidth;
|
||||||
|
ui_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_antenna_bias(bool antenna_bias) {
|
static void rad1o_ui_set_lna_power(bool _lna_on)
|
||||||
hackrf_ui_setAntennaBias(antenna_bias);
|
{
|
||||||
|
lna_on = _lna_on;
|
||||||
|
ui_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rad1o_ui_set_clock_source(clock_source_t source) {
|
static void rad1o_ui_set_bb_lna_gain(const uint32_t gain_db)
|
||||||
hackrf_ui_setClockSource(source);
|
{
|
||||||
|
bblna_gain = gain_db;
|
||||||
|
ui_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool rad1o_ui_operacake_gpio_compatible(void) {
|
static void rad1o_ui_set_bb_vga_gain(const uint32_t gain_db)
|
||||||
|
{
|
||||||
|
bbvga_gain = gain_db;
|
||||||
|
ui_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rad1o_ui_set_bb_tx_vga_gain(const uint32_t gain_db)
|
||||||
|
{
|
||||||
|
bbtxvga_gain = gain_db;
|
||||||
|
ui_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rad1o_ui_set_first_if_frequency(const uint64_t frequency
|
||||||
|
__attribute__((unused)))
|
||||||
|
{
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rad1o_ui_set_filter(const rf_path_filter_t filter
|
||||||
|
__attribute__((unused)))
|
||||||
|
{
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rad1o_ui_set_antenna_bias(bool antenna_bias __attribute__((unused)))
|
||||||
|
{
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rad1o_ui_set_clock_source(clock_source_t source
|
||||||
|
__attribute__((unused)))
|
||||||
|
{
|
||||||
|
// Not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rad1o_ui_set_transceiver_mode(transceiver_mode_t mode)
|
||||||
|
{
|
||||||
|
trx_mode = mode;
|
||||||
|
ui_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool rad1o_ui_operacake_gpio_compatible(void)
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +320,11 @@ static const hackrf_ui_t rad1o_ui = {
|
|||||||
&rad1o_ui_set_filter,
|
&rad1o_ui_set_filter,
|
||||||
&rad1o_ui_set_antenna_bias,
|
&rad1o_ui_set_antenna_bias,
|
||||||
&rad1o_ui_set_clock_source,
|
&rad1o_ui_set_clock_source,
|
||||||
|
&rad1o_ui_set_transceiver_mode,
|
||||||
&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;
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,13 @@ endif()
|
|||||||
if(BOARD STREQUAL "RAD1O")
|
if(BOARD STREQUAL "RAD1O")
|
||||||
SET(SRC_M4
|
SET(SRC_M4
|
||||||
${SRC_M4}
|
${SRC_M4}
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/display.c"
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/print.c"
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/render.c"
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/decoder.c"
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/smallfonts.c"
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/draw.c"
|
||||||
|
"${PATH_HACKRF_FIRMWARE_COMMON}/rad1o/ubuntu18.c"
|
||||||
"${PATH_HACKRF_FIRMWARE_COMMON}/ui_rad1o.c"
|
"${PATH_HACKRF_FIRMWARE_COMMON}/ui_rad1o.c"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@ -262,6 +262,8 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) {
|
|||||||
|
|
||||||
_transceiver_mode = new_transceiver_mode;
|
_transceiver_mode = new_transceiver_mode;
|
||||||
|
|
||||||
|
hackrf_ui()->set_transceiver_mode(_transceiver_mode);
|
||||||
|
|
||||||
switch (_transceiver_mode) {
|
switch (_transceiver_mode) {
|
||||||
case TRANSCEIVER_MODE_RX_SWEEP:
|
case TRANSCEIVER_MODE_RX_SWEEP:
|
||||||
case TRANSCEIVER_MODE_RX:
|
case TRANSCEIVER_MODE_RX:
|
||||||
|
Reference in New Issue
Block a user