Prusa MINI Firmware overview
gcode_thumb_decoder.h
Go to the documentation of this file.
1 #ifndef GCODE_THUMB_DECODER_H
2 #define GCODE_THUMB_DECODER_H
3 
4 // bod 2 - uchodit parser na g-code (bohuzel nemuzu pouzit boost::spirit, to by
5 // me Robert asi sezral :) ) ale ono to nebude tak strasne - jde o to, ze se
6 // musi cist radek zacinajici na strednik, pak vyignorovat mezery a pak jen
7 // nacist radek az do konce Problem je ale v tom, ze ne kazdej comment je
8 // obrazek, cili nejdriv musim ve fajlu najit nasledujici: ; thumbnail begin
9 // 220x165 25968 ma to u sebe velikost v pixelech a dylku v bajtech pak to bez
10 // preruseni (zatim!) obsahuje base64 definici a konci to: ; thumbnail end takze
11 // se bude cist po radkach a bude se hledat radek, ktery zacina na "; thumbnail"
12 // pak se zkontroluje, jestli je to spravna velikost (protoze jsou tam 3 a ja
13 // chci ten prostredni) Navic jsem nucen pouzivat ten hnusnej FILE interface,
14 // protoze na Mini asi nic jinyho nebude
15 
16 #include "../Marlin/src/libs/circularqueue.h"
17 #include "base64_stream_decoder.h"
18 #include <algorithm>
19 #include <stdio.h>
20 #include <string.h>
21 
22 #include "ff.h"
23 
24 // jeste budu asi potrebovat nacitac cele radky, pricemz musim dat pozor, aby se
25 // precetlo max 80 znaku a vse ostatni az do \n se zahodilo
26 struct SLine {
27  static const size_t MAX = 80;
29  size_t
30  expectedLineSize; // ocekavana delka radky, ktera chtela byt nactena - u
31  // base64 je nutne zkontrolovat, ze mi nic nevypadlo
32  uint8_t l[MAX + 1]; // MAX+1 zamerne, abych mohl mit posledni bajt 0
33  SLine() {
34  Reset();
35  }
37  if (size < MAX) {
38  l[size++] = b;
39  l[size] = 0; // prepare termination
40  }
42  }
43  inline void Reset() {
44  size = 0;
45  expectedLineSize = 0;
46  l[0] = l[MAX] = 0;
47  }
48  operator const char *() const {
49  return (const char *)(l);
50  }
51 
52  bool IsBeginThumbnail() const;
53  bool IsEndThumbnail() const;
54 };
55 
56 // zamerne je to singleton, aby se vsude vynutilo, ze je opravdu jen jedna
57 // instance v celem programu Lze to pripadne predelat, ale je potreba myslet na
58 // to, ze dekodovaci automaty nejsou bezestavove a musi nekde svoje stavy
59 // pamatovat.
62  }
63 
64  Base64StreamDecoder base64SD;
65 
66  // dale budu potrebovat jednoduchy kruhovy buffer, kam se zdekoduje base64
67  // radka radka ma max 80 znaku, z cehoz je 77 platnych base64 Jelikoz base64
68  // znamena, ze se vezme 3x8 bitu, spoji se do 24bitu a z toho se udela 4x6
69  // bitu, tak je to redukce 4:3 jestli dobre pocitam cili 77/4*3 ~ 58B
70  // pricemz neco muze pribyt z predchoziho radku ... rekneme 60B bude kruhovy
71  // buffer, akorat to budu chtit na 2 radky, abych mohl navazovat (da se
72  // velikost optimalizovat)
74  TBytesQueue bytesQ;
75 
76  // tohle nacte jeden bajt z fajlu
77  bool ReadByte(FIL *f, uint8_t &byte);
78 
79  // @return false, pokud se doslo na konec fajlu
80  // pritom muze byt neco v line nactene, to je normalni
81  bool ReadLine(FIL *f, SLine &line);
82 
83  bool AppendBase64Chars(const char *src, TBytesQueue &bytesQ);
84 
85  // tak, tady uz nastava problem - idealne bych mel vracet jednotlivy bajty
86  // (to jeste souvisi s png interfacem) takze parsovat celou lajnu se mi moc
87  // nelibi bude potreba ten dekoder predelat tak, aby nekoncil pripadne s
88  // chybou, ale nechal si par bajtu pretyct do dalsiho volani cili to bude
89  // muset bejt automat... Idealne bych to cely jakoby potreboval otocit - png
90  // vola void user_read_data(png_structp png_ptr, png_bytep data, png_size_t
91  // length); a dale mozna chybova a warningova funkce: void
92  // user_error_fn(png_structp png_ptr, png_const_charp error_msg); void
93  // user_warning_fn(png_structp png_ptr, png_const_charp warning_msg); Takze,
94  // png ocekava nacteni daneho poctu bajtu do sveho bufferu, cili uplne cteni
95  // cele radky mozna nebude potreba bude stacit, kdyz dokazu precist stabilne
96  // 3 bajty - protoze to je max. blok, ktery mi base64 decoder da.
97 
98  bool LineIsBase64(const char *l, TBytesQueue &bytesQ) {
99  // lajna musi zacinat '; ' a pak tam musi byt base64 znaky
100  // pokud to bude cokoli jineho, vracim false a error
101  if (l[0] != ';' || l[1] != ' ')
102  return false;
103  // tohle se vola pote, co se zkontroluje, jestli dana lajna neni
104  // thumbnail end, takze se tim uz nemusim zabyvat
105  return AppendBase64Chars(l + 2, bytesQ);
106  }
107 
108  // tohle bude hledat ve fajlu komentare ve formatu ; thumbnail atd.
109  // ted je to hodne podobny tomu, jak ma vypadat png read funkce
110  // dostane pointer na buffer a pocet bajtu, ktere ma nacist (coz musi
111  // splnit)
112  // void user_read_data(FILE *f, uint8_t *data, size_t length){
113 
114  // tak jeste jinak
115  // read pro fatfs vypada takto:
116  // int _f_fread(struct _reent* _r, void* pv, char* pc, int n)
117  //{
118  // UINT br = 0;
119  // f_read(&fil, pc, n, &br);
120  // return br;
121  //}
122  // nelze pouzit normalni libc read, protoze to zas neni FILE*
123  // pv me asi nezajima, nevim, co to je
124  // pc je buffer, do kteryho to cpu
125  // n je pocet znaku, ktery chci nacist
126  // vracim pocet nactenych znaku nebo -1, pokud pruser
127  // jeste si sem naprasim file pointer...
128  // _r je pointer na reentrant, cili na sFILE strukturu ... v mym pripade to
129  // bude to FILE
130 
131  // Nekde venku budu potrebovat nejakej context, kde si uchovam stav automatu
132  // stavy budou:
133  // searching - hledam zacatek thumbnailu
134  // base64 - ctu base64
135  // end - neni nic dalsiho
136 
137  enum class States : uint8_t { Searching,
138  Base64,
139  End,
140  Error };
141 
142  States state = States::Searching;
143 
144 public:
145  inline static GCodeThumbDecoder &Instance() {
146  static GCodeThumbDecoder i;
147  return i;
148  }
149 
150  // idealne to udelat tak, ze bych se vubec nemusel zabejvat koncema radku -
151  // normalni search automat, kterej proste ve fajlu najde spravnou uvodni
152  // sekvenci
153 
154  int Read(FIL *f, char *pc, int n);
155 
156  void Reset() {
157  // opakovani pokusu - cteni po vice bajtech
158  // nutno resetovat automaty, coz je taky potreba vyresit
159  state = States::Searching;
160  base64SD.Reset();
161  while (!bytesQ.isEmpty())
162  bytesQ.dequeue();
163  }
164 };
165 
166 #endif // GCODE_THUMB_DECODER_H
CircularQueue::isEmpty
bool isEmpty()
Checks if the queue has no items.
Definition: circularqueue.h:101
SLine::AppendByte
void AppendByte(uint8_t b)
Definition: gcode_thumb_decoder.h:36
FIL
Definition: ff.h:155
gcode_thumb_decoder.h
GCodeThumbDecoder::Instance
static GCodeThumbDecoder & Instance()
Definition: gcode_thumb_decoder.h:145
GCodeThumbDecoder::Reset
void Reset()
Definition: gcode_thumb_decoder.h:156
SLine::size
uint8_t size
Definition: gcode_thumb_decoder.h:28
i
uint8_t i
Definition: screen_test_graph.c:72
CircularQueue::dequeue
T dequeue()
Removes and returns a item from the queue.
Definition: circularqueue.h:65
SLine
Definition: gcode_thumb_decoder.h:26
SLine::l
uint8_t l[MAX+1]
Definition: gcode_thumb_decoder.h:32
SLine::SLine
SLine()
Definition: gcode_thumb_decoder.h:33
GCodeThumbDecoder::Read
int Read(FIL *f, char *pc, int n)
Definition: gcode_thumb_decoder.cpp:71
SLine::expectedLineSize
size_t expectedLineSize
Definition: gcode_thumb_decoder.h:30
min
#define min(a, b)
Definition: wiring_constants.h:36
SLine::Reset
void Reset()
Definition: gcode_thumb_decoder.h:43
Base64StreamDecoder::ConsumeChar
int ConsumeChar(char c, uint8_t *out)
Definition: base64_stream_decoder.cpp:28
Base64StreamDecoder::Reset
void Reset()
Definition: base64_stream_decoder.h:26
ff.h
SLine::MAX
static const size_t MAX
Definition: gcode_thumb_decoder.h:27
Base64StreamDecoder
Definition: base64_stream_decoder.h:16
uint8_t
const uint8_t[]
Definition: 404_html.c:3
f_eof
#define f_eof(fp)
Definition: ff.h:277
CircularQueue< uint8_t, 128 >
FR_OK
Definition: ff.h:215
base64_stream_decoder.h
SLine::IsEndThumbnail
bool IsEndThumbnail() const
Definition: gcode_thumb_decoder.cpp:29
g29_auto.lines
int lines
Definition: g29_auto.py:141
GCodeThumbDecoder
Definition: gcode_thumb_decoder.h:60
byte
uint8_t byte
Definition: wiring_constants.h:112
createSpeedLookupTable.b
list b
Definition: createSpeedLookupTable.py:30
SLine::IsBeginThumbnail
bool IsBeginThumbnail() const
Definition: gcode_thumb_decoder.cpp:3
CircularQueue::enqueue
bool enqueue(T const &item)
Adds an item to the queue.
Definition: circularqueue.h:84
UINT
unsigned int UINT
Definition: onboard_sd.h:16
f_read
FRESULT f_read(FIL *fp, void *buff, UINT btr, UINT *br)
Definition: ff.c:3499