1b05f4bc4Sgiulcioffi/**************************************************************************************
2b05f4bc4Sgiulcioffi   INCLUDE
3b05f4bc4Sgiulcioffi **************************************************************************************/
4b05f4bc4Sgiulcioffi
5b05f4bc4Sgiulcioffi#include "lzss.h"
6b05f4bc4Sgiulcioffi
7b05f4bc4Sgiulcioffi#include <stdlib.h>
8b05f4bc4Sgiulcioffi#include <stdint.h>
9b05f4bc4Sgiulcioffi
10b05f4bc4Sgiulcioffi#include <MKRNB.h>
11b05f4bc4Sgiulcioffi#include <FlashStorage.h>
12b05f4bc4Sgiulcioffi
13b05f4bc4Sgiulcioffi/**************************************************************************************
14b05f4bc4Sgiulcioffi   DEFINE
15b05f4bc4Sgiulcioffi **************************************************************************************/
16b05f4bc4Sgiulcioffi
17b05f4bc4Sgiulcioffi#define EI 11             /* typically 10..13 */
18b05f4bc4Sgiulcioffi#define EJ  4             /* typically 4..5 */
19b05f4bc4Sgiulcioffi#define P   1             /* If match length <= P then output one character */
20b05f4bc4Sgiulcioffi#define N (1 << EI)       /* buffer size */
21b05f4bc4Sgiulcioffi#define F ((1 << EJ) + 1) /* lookahead buffer size */
22b05f4bc4Sgiulcioffi
23b05f4bc4Sgiulcioffi#define LZSS_EOF       (-1)
24b05f4bc4Sgiulcioffi
25b05f4bc4Sgiulcioffi#define FPUTC_BUF_SIZE (512)
26b05f4bc4Sgiulcioffi#define FGETC_BUF_SIZE (512)
27b05f4bc4Sgiulcioffi
28b05f4bc4Sgiulcioffi/**************************************************************************************
29b05f4bc4Sgiulcioffi   GLOBAL VARIABLES
30b05f4bc4Sgiulcioffi **************************************************************************************/
31b05f4bc4Sgiulcioffi
32b05f4bc4Sgiulcioffiextern NBFileUtils fileUtils;
33b05f4bc4Sgiulcioffiextern FlashClass mcu_flash;
34b05f4bc4Sgiulcioffiextern const char * UPDATE_FILE_NAME_LZSS;
35b05f4bc4Sgiulcioffi
36b05f4bc4Sgiulcioffistatic uint32_t SKETCH_START = 0;
37b05f4bc4Sgiulcioffistatic uint32_t LZSS_FILE_SIZE = 0;
38b05f4bc4Sgiulcioffi
39b05f4bc4Sgiulcioffiint bit_buffer = 0, bit_mask = 128;
40b05f4bc4Sgiulcioffiunsigned char buffer[N * 2];
41b05f4bc4Sgiulcioffi
42b05f4bc4Sgiulcioffistatic char write_buf[FPUTC_BUF_SIZE];
43b05f4bc4Sgiulcioffistatic size_t write_buf_num_bytes = 0;
44b05f4bc4Sgiulcioffistatic size_t bytes_written_fputc = 0;
45b05f4bc4Sgiulcioffistatic size_t bytes_written_flash = 0;
46b05f4bc4Sgiulcioffistatic uint32_t flash_addr = 0;
47b05f4bc4Sgiulcioffi
48b05f4bc4Sgiulcioffi/**************************************************************************************
49b05f4bc4Sgiulcioffi   PUBLIC FUNCTIONS
50b05f4bc4Sgiulcioffi **************************************************************************************/
51b05f4bc4Sgiulcioffi
52768d7549Sgiulcioffivoid lzss_init(uint32_t const sketch_start)
53b05f4bc4Sgiulcioffi{
54768d7549Sgiulcioffi  SKETCH_START = sketch_start;
55768d7549Sgiulcioffi  flash_addr = sketch_start;
56768d7549Sgiulcioffi  LZSS_FILE_SIZE = fileUtils.listFile(UPDATE_FILE_NAME_LZSS);
57b05f4bc4Sgiulcioffi}
58b05f4bc4Sgiulcioffi
59b05f4bc4Sgiulcioffivoid lzss_flush()
60b05f4bc4Sgiulcioffi{
61b05f4bc4Sgiulcioffi  bytes_written_fputc += write_buf_num_bytes;
62b05f4bc4Sgiulcioffi
63768d7549Sgiulcioffi  /* Only write to the flash once we've surpassed
64768d7549Sgiulcioffi   * the SBU in the update binary.
65768d7549Sgiulcioffi   */
66768d7549Sgiulcioffi  if (bytes_written_fputc > (SKETCH_START - 0x2000))
67768d7549Sgiulcioffi  {
68768d7549Sgiulcioffi    mcu_flash.write((void*)flash_addr, write_buf, write_buf_num_bytes);
69768d7549Sgiulcioffi    flash_addr += write_buf_num_bytes;
70768d7549Sgiulcioffi  }
71b05f4bc4Sgiulcioffi
72b05f4bc4Sgiulcioffi  write_buf_num_bytes = 0;
73b05f4bc4Sgiulcioffi}
74b05f4bc4Sgiulcioffi
75b05f4bc4Sgiulcioffi/**************************************************************************************
76b05f4bc4Sgiulcioffi   PRIVATE FUNCTIONS
77b05f4bc4Sgiulcioffi **************************************************************************************/
78b05f4bc4Sgiulcioffi
79b05f4bc4Sgiulcioffivoid lzss_fputc(int const c)
80b05f4bc4Sgiulcioffi{
81b05f4bc4Sgiulcioffi  /* Buffer the decompressed data into a buffer so
82b05f4bc4Sgiulcioffi   * we can perform block writes and don't need to
83b05f4bc4Sgiulcioffi   * write every byte singly on the flash (which
84b05f4bc4Sgiulcioffi   * wouldn't be possible anyway).
85b05f4bc4Sgiulcioffi   */
86b05f4bc4Sgiulcioffi  write_buf[write_buf_num_bytes] = static_cast<char>(c);
87b05f4bc4Sgiulcioffi  write_buf_num_bytes++;
88b05f4bc4Sgiulcioffi
89b05f4bc4Sgiulcioffi  /* The write buffer is full of decompressed
90b05f4bc4Sgiulcioffi   * data, write it to the flash now.
91b05f4bc4Sgiulcioffi   */
92b05f4bc4Sgiulcioffi  if (write_buf_num_bytes == FPUTC_BUF_SIZE)
93b05f4bc4Sgiulcioffi    lzss_flush();
94b05f4bc4Sgiulcioffi}
95b05f4bc4Sgiulcioffi
96b05f4bc4Sgiulcioffiint lzss_fgetc()
97b05f4bc4Sgiulcioffi{
98b05f4bc4Sgiulcioffi  static uint8_t read_buf[FGETC_BUF_SIZE];
99b05f4bc4Sgiulcioffi  static size_t read_buf_pos = FGETC_BUF_SIZE;
100b05f4bc4Sgiulcioffi  static size_t bytes_read_fgetc = 0;
101b05f4bc4Sgiulcioffi  static size_t bytes_read_from_modem = 0;
102b05f4bc4Sgiulcioffi
103b05f4bc4Sgiulcioffi  /* lzss_file_size is set within SBUBoot:main
104b05f4bc4Sgiulcioffi   * and contains the size of the LZSS file. Once
105b05f4bc4Sgiulcioffi   * all those bytes have been read its time to return
106b05f4bc4Sgiulcioffi   * LZSS_EOF in order to signal that the end of
107b05f4bc4Sgiulcioffi   * the file has been reached.
108b05f4bc4Sgiulcioffi   */
109b05f4bc4Sgiulcioffi  if (bytes_read_fgetc == LZSS_FILE_SIZE)
110b05f4bc4Sgiulcioffi    return LZSS_EOF;
111b05f4bc4Sgiulcioffi
112b05f4bc4Sgiulcioffi  /* If there is no data left to be read from the read buffer
113b05f4bc4Sgiulcioffi   * than read a new block and store it into the read buffer.
114b05f4bc4Sgiulcioffi   */
115b05f4bc4Sgiulcioffi  if (read_buf_pos == FGETC_BUF_SIZE)
116b05f4bc4Sgiulcioffi  {
117b05f4bc4Sgiulcioffi    /* Read the next block from the flash memory. */
118b05f4bc4Sgiulcioffi    bytes_read_from_modem += fileUtils.readBlock(UPDATE_FILE_NAME_LZSS, bytes_read_from_modem, FGETC_BUF_SIZE, read_buf);
119b05f4bc4Sgiulcioffi    /* Reset the read buffer position. */
120b05f4bc4Sgiulcioffi    read_buf_pos = 0;
121b05f4bc4Sgiulcioffi  }
122b05f4bc4Sgiulcioffi
123b05f4bc4Sgiulcioffi  uint8_t const c = read_buf[read_buf_pos];
124b05f4bc4Sgiulcioffi  read_buf_pos++;
125b05f4bc4Sgiulcioffi  bytes_read_fgetc++;
126b05f4bc4Sgiulcioffi
127b05f4bc4Sgiulcioffi  return c;
128b05f4bc4Sgiulcioffi}
129b05f4bc4Sgiulcioffi
130b05f4bc4Sgiulcioffi/**************************************************************************************
131b05f4bc4Sgiulcioffi   LZSS FUNCTIONS
132b05f4bc4Sgiulcioffi **************************************************************************************/
133b05f4bc4Sgiulcioffi
134b05f4bc4Sgiulcioffivoid putbit1(void)
135b05f4bc4Sgiulcioffi{
136b05f4bc4Sgiulcioffi    bit_buffer |= bit_mask;
137b05f4bc4Sgiulcioffi    if ((bit_mask >>= 1) == 0) {
138b05f4bc4Sgiulcioffi        lzss_fputc(bit_buffer);
139b05f4bc4Sgiulcioffi        bit_buffer = 0;  bit_mask = 128;
140b05f4bc4Sgiulcioffi    }
141b05f4bc4Sgiulcioffi}
142b05f4bc4Sgiulcioffi
143b05f4bc4Sgiulcioffivoid putbit0(void)
144b05f4bc4Sgiulcioffi{
145b05f4bc4Sgiulcioffi    if ((bit_mask >>= 1) == 0) {
146b05f4bc4Sgiulcioffi        lzss_fputc(bit_buffer);
147b05f4bc4Sgiulcioffi        bit_buffer = 0;  bit_mask = 128;
148b05f4bc4Sgiulcioffi    }
149b05f4bc4Sgiulcioffi}
150b05f4bc4Sgiulcioffi
151b05f4bc4Sgiulcioffivoid output1(int c)
152b05f4bc4Sgiulcioffi{
153b05f4bc4Sgiulcioffi    int mask;
154b05f4bc4Sgiulcioffi
155b05f4bc4Sgiulcioffi    putbit1();
156b05f4bc4Sgiulcioffi    mask = 256;
157b05f4bc4Sgiulcioffi    while (mask >>= 1) {
158b05f4bc4Sgiulcioffi        if (c & mask) putbit1();
159b05f4bc4Sgiulcioffi        else putbit0();
160b05f4bc4Sgiulcioffi    }
161b05f4bc4Sgiulcioffi}
162b05f4bc4Sgiulcioffi
163b05f4bc4Sgiulcioffivoid output2(int x, int y)
164b05f4bc4Sgiulcioffi{
165b05f4bc4Sgiulcioffi    int mask;
166b05f4bc4Sgiulcioffi
167b05f4bc4Sgiulcioffi    putbit0();
168b05f4bc4Sgiulcioffi    mask = N;
169b05f4bc4Sgiulcioffi    while (mask >>= 1) {
170b05f4bc4Sgiulcioffi        if (x & mask) putbit1();
171b05f4bc4Sgiulcioffi        else putbit0();
172b05f4bc4Sgiulcioffi    }
173b05f4bc4Sgiulcioffi    mask = (1 << EJ);
174b05f4bc4Sgiulcioffi    while (mask >>= 1) {
175b05f4bc4Sgiulcioffi        if (y & mask) putbit1();
176b05f4bc4Sgiulcioffi        else putbit0();
177b05f4bc4Sgiulcioffi    }
178b05f4bc4Sgiulcioffi}
179b05f4bc4Sgiulcioffi
180b05f4bc4Sgiulcioffiint getbit(int n) /* get n bits */
181b05f4bc4Sgiulcioffi{
182b05f4bc4Sgiulcioffi    int i, x;
183b05f4bc4Sgiulcioffi    static int buf, mask = 0;
184b05f4bc4Sgiulcioffi
185b05f4bc4Sgiulcioffi    x = 0;
186b05f4bc4Sgiulcioffi    for (i = 0; i < n; i++) {
187b05f4bc4Sgiulcioffi        if (mask == 0) {
188b05f4bc4Sgiulcioffi            if ((buf = lzss_fgetc()) == LZSS_EOF) return LZSS_EOF;
189b05f4bc4Sgiulcioffi            mask = 128;
190b05f4bc4Sgiulcioffi        }
191b05f4bc4Sgiulcioffi        x <<= 1;
192b05f4bc4Sgiulcioffi        if (buf & mask) x++;
193b05f4bc4Sgiulcioffi        mask >>= 1;
194b05f4bc4Sgiulcioffi    }
195b05f4bc4Sgiulcioffi    return x;
196b05f4bc4Sgiulcioffi}
197b05f4bc4Sgiulcioffi
198b05f4bc4Sgiulcioffivoid lzss_decode(void)
199b05f4bc4Sgiulcioffi{
200b05f4bc4Sgiulcioffi    int i, j, k, r, c;
201b05f4bc4Sgiulcioffi
202b05f4bc4Sgiulcioffi    for (i = 0; i < N - F; i++) buffer[i] = ' ';
203b05f4bc4Sgiulcioffi    r = N - F;
204b05f4bc4Sgiulcioffi    while ((c = getbit(1)) != LZSS_EOF) {
205b05f4bc4Sgiulcioffi        if (c) {
206b05f4bc4Sgiulcioffi            if ((c = getbit(8)) == LZSS_EOF) break;
207b05f4bc4Sgiulcioffi            lzss_fputc(c);
208b05f4bc4Sgiulcioffi            buffer[r++] = c;  r &= (N - 1);
209b05f4bc4Sgiulcioffi        } else {
210b05f4bc4Sgiulcioffi            if ((i = getbit(EI)) == LZSS_EOF) break;
211b05f4bc4Sgiulcioffi            if ((j = getbit(EJ)) == LZSS_EOF) break;
212b05f4bc4Sgiulcioffi            for (k = 0; k <= j + 1; k++) {
213b05f4bc4Sgiulcioffi                c = buffer[(i + k) & (N - 1)];
214b05f4bc4Sgiulcioffi                lzss_fputc(c);
215b05f4bc4Sgiulcioffi                buffer[r++] = c;  r &= (N - 1);
216b05f4bc4Sgiulcioffi            }
217b05f4bc4Sgiulcioffi        }
218b05f4bc4Sgiulcioffi    }
219768d7549Sgiulcioffi}
220