HackRF-Treasure-Chest/Software/portapack-mayhem/hackrf/firmware/common/rad1o/decoder.c
2022-09-22 09:26:57 -07:00

128 lines
2.6 KiB
C

#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;
}