1807f4508SAlexander Entinger/**************************************************************************************
2807f4508SAlexander Entinger   INCLUDE
3807f4508SAlexander Entinger **************************************************************************************/
4807f4508SAlexander Entinger
5807f4508SAlexander Entinger#include "lzss.h"
6807f4508SAlexander Entinger
7807f4508SAlexander Entinger#include <stdlib.h>
8807f4508SAlexander Entinger#include <stdint.h>
9807f4508SAlexander Entinger
10807f4508SAlexander Entinger#include <MKRGSM.h>
11807f4508SAlexander Entinger#include <FlashStorage.h>
12807f4508SAlexander Entinger
13807f4508SAlexander Entinger/**************************************************************************************
14807f4508SAlexander Entinger   DEFINE
15807f4508SAlexander Entinger **************************************************************************************/
16807f4508SAlexander Entinger
17807f4508SAlexander Entinger#define EI 11             /* typically 10..13 */
18807f4508SAlexander Entinger#define EJ  4             /* typically 4..5 */
19807f4508SAlexander Entinger#define P   1             /* If match length <= P then output one character */
20807f4508SAlexander Entinger#define N (1 << EI)       /* buffer size */
21807f4508SAlexander Entinger#define F ((1 << EJ) + 1) /* lookahead buffer size */
22807f4508SAlexander Entinger
23807f4508SAlexander Entinger#define LZSS_EOF       (-1)
24807f4508SAlexander Entinger
25807f4508SAlexander Entinger#define FPUTC_BUF_SIZE (512)
26807f4508SAlexander Entinger#define FGETC_BUF_SIZE (512)
27807f4508SAlexander Entinger
28807f4508SAlexander Entinger/**************************************************************************************
29807f4508SAlexander Entinger   GLOBAL VARIABLES
30807f4508SAlexander Entinger **************************************************************************************/
31807f4508SAlexander Entinger
32807f4508SAlexander Entingerextern GSMFileUtils fileUtils;
33807f4508SAlexander Entingerextern FlashClass mcu_flash;
34807f4508SAlexander Entingerextern const char * UPDATE_FILE_NAME_LZSS;
35807f4508SAlexander Entinger
36807f4508SAlexander Entingerstatic uint32_t SKETCH_START = 0;
37807f4508SAlexander Entingerstatic uint32_t LZSS_FILE_SIZE = 0;
38807f4508SAlexander Entinger
39807f4508SAlexander Entingerint bit_buffer = 0, bit_mask = 128;
40807f4508SAlexander Entingerunsigned char buffer[N * 2];
41807f4508SAlexander Entinger
42807f4508SAlexander Entingerstatic char write_buf[FPUTC_BUF_SIZE];
43807f4508SAlexander Entingerstatic size_t write_buf_num_bytes = 0;
44807f4508SAlexander Entingerstatic size_t bytes_written_fputc = 0;
45807f4508SAlexander Entingerstatic size_t bytes_written_flash = 0;
46807f4508SAlexander Entingerstatic uint32_t flash_addr = 0;
47807f4508SAlexander Entinger
48807f4508SAlexander Entinger/**************************************************************************************
49807f4508SAlexander Entinger   PUBLIC FUNCTIONS
50807f4508SAlexander Entinger **************************************************************************************/
51807f4508SAlexander Entinger
52807f4508SAlexander Entingervoid lzss_init(uint32_t const sketch_start)
53807f4508SAlexander Entinger{
54807f4508SAlexander Entinger  SKETCH_START = sketch_start;
55807f4508SAlexander Entinger  flash_addr = sketch_start;
56807f4508SAlexander Entinger  LZSS_FILE_SIZE = fileUtils.listFile(UPDATE_FILE_NAME_LZSS);
57807f4508SAlexander Entinger}
58807f4508SAlexander Entinger
59807f4508SAlexander Entingervoid lzss_flush()
60807f4508SAlexander Entinger{
61807f4508SAlexander Entinger  bytes_written_fputc += write_buf_num_bytes;
62807f4508SAlexander Entinger
63807f4508SAlexander Entinger  /* Only write to the flash once we've surpassed
64807f4508SAlexander Entinger   * the SSU in the update binary.
65807f4508SAlexander Entinger   */
66807f4508SAlexander Entinger  if (bytes_written_fputc > (SKETCH_START - 0x2000))
67807f4508SAlexander Entinger  {
68807f4508SAlexander Entinger    mcu_flash.write((void*)flash_addr, write_buf, write_buf_num_bytes);
69807f4508SAlexander Entinger    flash_addr += write_buf_num_bytes;
70807f4508SAlexander Entinger  }
71807f4508SAlexander Entinger
72807f4508SAlexander Entinger  write_buf_num_bytes = 0;
73807f4508SAlexander Entinger}
74807f4508SAlexander Entinger
75807f4508SAlexander Entinger/**************************************************************************************
76807f4508SAlexander Entinger   PRIVATE FUNCTIONS
77807f4508SAlexander Entinger **************************************************************************************/
78807f4508SAlexander Entinger
79807f4508SAlexander Entingervoid lzss_fputc(int const c)
80807f4508SAlexander Entinger{
81807f4508SAlexander Entinger  /* Buffer the decompressed data into a buffer so
82807f4508SAlexander Entinger   * we can perform block writes and don't need to
83807f4508SAlexander Entinger   * write every byte singly on the flash (which
84807f4508SAlexander Entinger   * wouldn't be possible anyway).
85807f4508SAlexander Entinger   */
86807f4508SAlexander Entinger  write_buf[write_buf_num_bytes] = static_cast<char>(c);
87807f4508SAlexander Entinger  write_buf_num_bytes++;
88807f4508SAlexander Entinger
89807f4508SAlexander Entinger  /* The write buffer is full of decompressed
90807f4508SAlexander Entinger   * data, write it to the flash now.
91807f4508SAlexander Entinger   */
92807f4508SAlexander Entinger  if (write_buf_num_bytes == FPUTC_BUF_SIZE)
93807f4508SAlexander Entinger    lzss_flush();
94807f4508SAlexander Entinger}
95807f4508SAlexander Entinger
96807f4508SAlexander Entingerint lzss_fgetc()
97807f4508SAlexander Entinger{
98807f4508SAlexander Entinger  static uint8_t read_buf[FGETC_BUF_SIZE];
99807f4508SAlexander Entinger  static size_t read_buf_pos = FGETC_BUF_SIZE;
100807f4508SAlexander Entinger  static size_t bytes_read_fgetc = 0;
101807f4508SAlexander Entinger  static size_t bytes_read_from_modem = 0;
102807f4508SAlexander Entinger
103807f4508SAlexander Entinger  /* lzss_file_size is set within SSUBoot:main
104807f4508SAlexander Entinger   * and contains the size of the LZSS file. Once
105807f4508SAlexander Entinger   * all those bytes have been read its time to return
106807f4508SAlexander Entinger   * LZSS_EOF in order to signal that the end of
107807f4508SAlexander Entinger   * the file has been reached.
108807f4508SAlexander Entinger   */
109807f4508SAlexander Entinger  if (bytes_read_fgetc == LZSS_FILE_SIZE)
110807f4508SAlexander Entinger    return LZSS_EOF;
111807f4508SAlexander Entinger
112807f4508SAlexander Entinger  /* If there is no data left to be read from the read buffer
113807f4508SAlexander Entinger   * than read a new block and store it into the read buffer.
114807f4508SAlexander Entinger   */
115807f4508SAlexander Entinger  if (read_buf_pos == FGETC_BUF_SIZE)
116807f4508SAlexander Entinger  {
117807f4508SAlexander Entinger    /* Read the next block from the flash memory. */
118807f4508SAlexander Entinger    bytes_read_from_modem += fileUtils.readBlock(UPDATE_FILE_NAME_LZSS, bytes_read_from_modem, FGETC_BUF_SIZE, read_buf);
119807f4508SAlexander Entinger    /* Reset the read buffer position. */
120807f4508SAlexander Entinger    read_buf_pos = 0;
121807f4508SAlexander Entinger  }
122807f4508SAlexander Entinger
123807f4508SAlexander Entinger  uint8_t const c = read_buf[read_buf_pos];
124807f4508SAlexander Entinger  read_buf_pos++;
125807f4508SAlexander Entinger  bytes_read_fgetc++;
126807f4508SAlexander Entinger
127807f4508SAlexander Entinger  return c;
128807f4508SAlexander Entinger}
129807f4508SAlexander Entinger
130807f4508SAlexander Entinger/**************************************************************************************
131807f4508SAlexander Entinger   LZSS FUNCTIONS
132807f4508SAlexander Entinger **************************************************************************************/
133807f4508SAlexander Entinger
134807f4508SAlexander Entingervoid putbit1(void)
135807f4508SAlexander Entinger{
136807f4508SAlexander Entinger    bit_buffer |= bit_mask;
137807f4508SAlexander Entinger    if ((bit_mask >>= 1) == 0) {
138807f4508SAlexander Entinger        lzss_fputc(bit_buffer);
139807f4508SAlexander Entinger        bit_buffer = 0;  bit_mask = 128;
140807f4508SAlexander Entinger    }
141807f4508SAlexander Entinger}
142807f4508SAlexander Entinger
143807f4508SAlexander Entingervoid putbit0(void)
144807f4508SAlexander Entinger{
145807f4508SAlexander Entinger    if ((bit_mask >>= 1) == 0) {
146807f4508SAlexander Entinger        lzss_fputc(bit_buffer);
147807f4508SAlexander Entinger        bit_buffer = 0;  bit_mask = 128;
148807f4508SAlexander Entinger    }
149807f4508SAlexander Entinger}
150807f4508SAlexander Entinger
151807f4508SAlexander Entingervoid output1(int c)
152807f4508SAlexander Entinger{
153807f4508SAlexander Entinger    int mask;
154807f4508SAlexander Entinger
155807f4508SAlexander Entinger    putbit1();
156807f4508SAlexander Entinger    mask = 256;
157807f4508SAlexander Entinger    while (mask >>= 1) {
158807f4508SAlexander Entinger        if (c & mask) putbit1();
159807f4508SAlexander Entinger        else putbit0();
160807f4508SAlexander Entinger    }
161807f4508SAlexander Entinger}
162807f4508SAlexander Entinger
163807f4508SAlexander Entingervoid output2(int x, int y)
164807f4508SAlexander Entinger{
165807f4508SAlexander Entinger    int mask;
166807f4508SAlexander Entinger
167807f4508SAlexander Entinger    putbit0();
168807f4508SAlexander Entinger    mask = N;
169807f4508SAlexander Entinger    while (mask >>= 1) {
170807f4508SAlexander Entinger        if (x & mask) putbit1();
171807f4508SAlexander Entinger        else putbit0();
172807f4508SAlexander Entinger    }
173807f4508SAlexander Entinger    mask = (1 << EJ);
174807f4508SAlexander Entinger    while (mask >>= 1) {
175807f4508SAlexander Entinger        if (y & mask) putbit1();
176807f4508SAlexander Entinger        else putbit0();
177807f4508SAlexander Entinger    }
178807f4508SAlexander Entinger}
179807f4508SAlexander Entinger
180807f4508SAlexander Entingerint getbit(int n) /* get n bits */
181807f4508SAlexander Entinger{
182807f4508SAlexander Entinger    int i, x;
183807f4508SAlexander Entinger    static int buf, mask = 0;
184807f4508SAlexander Entinger
185807f4508SAlexander Entinger    x = 0;
186807f4508SAlexander Entinger    for (i = 0; i < n; i++) {
187807f4508SAlexander Entinger        if (mask == 0) {
188807f4508SAlexander Entinger            if ((buf = lzss_fgetc()) == LZSS_EOF) return LZSS_EOF;
189807f4508SAlexander Entinger            mask = 128;
190807f4508SAlexander Entinger        }
191807f4508SAlexander Entinger        x <<= 1;
192807f4508SAlexander Entinger        if (buf & mask) x++;
193807f4508SAlexander Entinger        mask >>= 1;
194807f4508SAlexander Entinger    }
195807f4508SAlexander Entinger    return x;
196807f4508SAlexander Entinger}
197807f4508SAlexander Entinger
198807f4508SAlexander Entingervoid lzss_decode(void)
199807f4508SAlexander Entinger{
200807f4508SAlexander Entinger    int i, j, k, r, c;
201807f4508SAlexander Entinger
202807f4508SAlexander Entinger    for (i = 0; i < N - F; i++) buffer[i] = ' ';
203807f4508SAlexander Entinger    r = N - F;
204807f4508SAlexander Entinger    while ((c = getbit(1)) != LZSS_EOF) {
205807f4508SAlexander Entinger        if (c) {
206807f4508SAlexander Entinger            if ((c = getbit(8)) == LZSS_EOF) break;
207807f4508SAlexander Entinger            lzss_fputc(c);
208807f4508SAlexander Entinger            buffer[r++] = c;  r &= (N - 1);
209807f4508SAlexander Entinger        } else {
210807f4508SAlexander Entinger            if ((i = getbit(EI)) == LZSS_EOF) break;
211807f4508SAlexander Entinger            if ((j = getbit(EJ)) == LZSS_EOF) break;
212807f4508SAlexander Entinger            for (k = 0; k <= j + 1; k++) {
213807f4508SAlexander Entinger                c = buffer[(i + k) & (N - 1)];
214807f4508SAlexander Entinger                lzss_fputc(c);
215807f4508SAlexander Entinger                buffer[r++] = c;  r &= (N - 1);
216807f4508SAlexander Entinger            }
217807f4508SAlexander Entinger        }
218807f4508SAlexander Entinger    }
219807f4508SAlexander Entinger}
220