123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407 |
- /*
- * Copyright (C) 2013-2018 by James Bowman <jamesb@excamera.com>
- * Gameduino 2/3 library for Arduino, Arduino Due, Teensy 3.2 and
- * ESP8266.
- */
- #ifndef _GD2_H_INCLUDED
- #define _GD2_H_INCLUDED
- #define GD2_VERSION "%VERSION"
- #if defined(RASPBERRY_PI) || defined(DUMPDEV)
- #include "wiring.h"
- #endif
- #include "Arduino.h"
- #include <stdarg.h>
- #define RGB(r, g, b) ((uint32_t)((((r) & 0xffL) << 16) | (((g) & 0xffL) << 8) | ((b) & 0xffL)))
- #define F8(x) (int((x) * 256L))
- #define F16(x) ((int32_t)((x) * 65536L))
- #define GD_CALIBRATE 1
- #define GD_TRIM 2
- #define GD_STORAGE 4
- #ifdef __SAM3X8E__
- #define __DUE__ 1
- #endif
- ////////////////////////////////////////////////////////////////////////
- // Decide if we want to compile in SDcard support
- //
- // For stock Arduino models: yes
- // Raspberry PI: no
- // Arduino Due: no
- //
- #if !defined(RASPBERRY_PI) && !defined(DUMPDEV)
- #define SDCARD 1
- #else
- #define SDCARD 0
- #endif
- #if defined(__DUE__)
- #define MOSI 11
- #define MISO 12
- #define SCK 13 // B.27
- class ASPI_t {
- public:
- void begin(void) {
- pinMode(MOSI, OUTPUT);
- pinMode(MISO, INPUT);
- pinMode(SCK, OUTPUT);
- digitalWrite(SCK, 0);
- // PIOB->PIO_PER = PIO_PB27;
- // PIOB->PIO_CODR = PIO_PB27;
- // PIOB->PIO_PUDR = PIO_PB27;
- }
- byte transfer(byte x ) {
- byte r = 0;
- for (byte i = 8; i; i--) {
- if (x & 0x80)
- PIOD->PIO_SODR = PIO_PD7;
- else
- PIOD->PIO_CODR = PIO_PD7;
- // digitalWrite(MOSI, (x >> 7) & 1);
- x <<= 1;
- // digitalWrite(SCK, 1);
- PIOB->PIO_SODR = PIO_PB27;
- r <<= 1;
- r |= digitalRead(MISO);
- // digitalWrite(SCK, 0);
- PIOB->PIO_CODR = PIO_PB27;
- }
- return r;
- }
- void transfer(byte*m, int s) {
- while (s--) {
- *m = transfer(*m);
- m++;
- }
- }
- };
- static class ASPI_t ASPI;
- #define SPI ASPI
- #endif
- #if defined(ARDUINO_STM32L4_BLACKICE)
- // BlackIce Board uses SPI1 on the Arduino header.
- #define SPI SPI1
- // Board Support:
- // JSON: http://www.hamnavoe.com/package_millerresearch_mystorm_index.json
- // Source: https://github.com/millerresearch/arduino-mystorm
- #endif
- #if SDCARD
- #if defined(VERBOSE) && (VERBOSE > 0)
- #define INFO(X) Serial.println((X))
- #if defined(RASPBERRY_PI)
- #define REPORT(VAR) fprintf(stderr, #VAR "=%d\n", (VAR))
- #else
- #define REPORT(VAR) (Serial.print(#VAR "="), Serial.print(VAR, DEC), Serial.print(' '), Serial.println(VAR, HEX))
- #endif
- #else
- #define INFO(X)
- #define REPORT(X)
- #endif
- struct dirent {
- char name[8];
- char ext[3];
- byte attribute;
- byte reserved[8];
- uint16_t cluster_hi; // FAT32 only
- uint16_t time;
- uint16_t date;
- uint16_t cluster;
- uint32_t size;
- };
- // https://www.sdcard.org/downloads/pls/simplified_specs/Part_1_Physical_Layer_Simplified_Specification_Ver_3.01_Final_100518.pdf
- // page 22
- // http://mac6.ma.psu.edu/space2008/RockSat/microController/sdcard_appnote_foust.pdf
- // http://elm-chan.org/docs/mmc/mmc_e.html
- // http://www.pjrc.com/tech/8051/ide/fat32.html
- #define FAT16 0
- #define FAT32 1
- #define DD
- class sdcard {
- public:
- void sel() {
- digitalWrite(pin, LOW);
- delay(1);
- }
- void desel() {
- digitalWrite(pin, HIGH);
- SPI.transfer(0xff); // force DO release
- }
- void sd_delay(byte n) {
- while (n--) {
- DD SPI.transfer(0xff);
- }
- }
- void cmd(byte cmd, uint32_t lba = 0, uint8_t crc = 0x95) {
- #if VERBOSE > 1
- Serial.print("cmd ");
- Serial.print(cmd, DEC);
- Serial.print(" ");
- Serial.print(lba, HEX);
- Serial.println();
- #endif
- sel();
- // DD SPI.transfer(0xff);
- DD SPI.transfer(0x40 | cmd);
- DD SPI.transfer(0xff & (lba >> 24));
- DD SPI.transfer(0xff & (lba >> 16));
- DD SPI.transfer(0xff & (lba >> 8));
- DD SPI.transfer(0xff & (lba));
- DD SPI.transfer(crc);
- // DD SPI.transfer(0xff);
- }
- byte response() {
- byte r;
- DD
- r = SPI.transfer(0xff);
- while (r & 0x80) {
- DD
- r = SPI.transfer(0xff);
- }
- return r;
- }
- byte R1() { // read response R1
- byte r = response();
- desel();
- SPI.transfer(0xff); // trailing byte
- return r;
- }
- byte sdR3(uint32_t &ocr) { // read response R3
- byte r = response();
- for (byte i = 4; i; i--)
- ocr = (ocr << 8) | SPI.transfer(0xff);
- SPI.transfer(0xff); // trailing byte
- desel();
- return r;
- }
- byte sdR7() { // read response R3
- byte r = response();
- for (byte i = 4; i; i--)
- // Serial.println(SPI.transfer(0xff), HEX);
- SPI.transfer(0xff);
- desel();
- return r;
- }
- void appcmd(byte cc, uint32_t lba = 0) {
- cmd(55); R1();
- cmd(cc, lba);
- }
- void begin(byte p) {
- byte type_code;
- byte sdhc;
- pin = p;
- pinMode(pin, OUTPUT);
- #if !defined(__DUE__) && !defined(TEENSYDUINO) && !defined(ARDUINO_ARCH_STM32L4)
- SPI.setClockDivider(SPI_CLOCK_DIV64);
- #endif
- desel();
- // for (;;) SPI.transfer(0xff);
- delay(50); // wait for boot
- sd_delay(10); // deselected, 80 pulses
- INFO("Attempting card reset... ");
- byte r1;
- static int attempts;
- attempts = 0;
- do { // reset, enter idle
- cmd(0);
- while ((r1 = SPI.transfer(0xff)) & 0x80)
- if (++attempts == 1000)
- goto finished;
- desel();
- SPI.transfer(0xff); // trailing byte
- REPORT(r1);
- } while (r1 != 1);
- INFO("reset ok\n");
- sdhc = 0;
- cmd(8, 0x1aa, 0x87);
- r1 = sdR7();
- sdhc = (r1 == 1);
- REPORT(sdhc);
- INFO("Sending card init command");
- attempts = 0;
- while (1) {
- appcmd(41, sdhc ? (1UL << 30) : 0); // card init
- r1 = R1();
- #if VERBOSE
- Serial.println(r1, HEX);
- #endif
- if ((r1 & 1) == 0)
- break;
- if (++attempts == 300)
- goto finished;
- delay(1);
- }
- INFO("OK");
- if (sdhc) {
- uint32_t OCR = 0;
- for (int i = 10; i; i--) {
- cmd(58);
- sdR3(OCR);
- REPORT(OCR);
- }
- ccs = 1UL & (OCR >> 30);
- } else {
- ccs = 0;
- }
- REPORT(ccs);
- // Test point: dump sector 0 to serial.
- // should see first 512 bytes of card, ending 55 AA.
- #if 0
- cmd17(0);
- for (int i = 0; i < 512; i++) {
- delay(10);
- byte b = SPI.transfer(0xff);
- Serial.print(b, HEX);
- Serial.print(' ');
- if ((i & 15) == 15)
- Serial.println();
- }
- desel();
- for (;;);
- #endif
- #if !defined(__DUE__) && !defined(ESP8266) && !defined(ARDUINO_ARCH_STM32L4)
- SPI.setClockDivider(SPI_CLOCK_DIV2);
- SPSR = (1 << SPI2X);
- #endif
- #if defined(ESP8266)
- SPI.setFrequency(40000000L);
- #endif
- type_code = rd(0x1be + 0x4);
- switch (type_code) {
- default:
- type = FAT16;
- break;
- case 0x0b:
- case 0x0c:
- type = FAT32;
- break;
- }
- REPORT(type_code);
- o_partition = 512L * rd4(0x1be + 0x8);
- sectors_per_cluster = rd(o_partition + 0xd);
- reserved_sectors = rd2(o_partition + 0xe);
- cluster_size = 512L * sectors_per_cluster;
- REPORT(sectors_per_cluster);
- // Serial.println("Bytes per sector: %d\n", rd2(o_partition + 0xb));
- // Serial.println("Sectors per cluster: %d\n", sectors_per_cluster);
- if (type == FAT16) {
- max_root_dir_entries = rd2(o_partition + 0x11);
- sectors_per_fat = rd2(o_partition + 0x16);
- o_fat = o_partition + 512L * reserved_sectors;
- o_root = o_fat + (2 * 512L * sectors_per_fat);
- // data area starts with cluster 2, so offset it here
- o_data = o_root + (max_root_dir_entries * 32L) - (2L * cluster_size);
- } else {
- uint32_t sectors_per_fat = rd4(o_partition + 0x24);
- root_dir_first_cluster = rd4(o_partition + 0x2c);
- uint32_t fat_begin_lba = (o_partition >> 9) + reserved_sectors;
- uint32_t cluster_begin_lba = (o_partition >> 9) + reserved_sectors + (2 * sectors_per_fat);
- o_fat = 512L * fat_begin_lba;
- o_root = (512L * (cluster_begin_lba + (root_dir_first_cluster - 2) * sectors_per_cluster));
- o_data = (512L * (cluster_begin_lba - 2 * sectors_per_cluster));
- }
- finished:
- INFO("finished");
- ;
- }
- void cmd17(uint32_t off) {
- if (ccs)
- cmd(17, off >> 9);
- else
- cmd(17, off & ~511L);
- R1();
- sel();
- while (SPI.transfer(0xff) != 0xfe)
- ;
- }
- void rdn(byte *d, uint32_t off, uint16_t n) {
- cmd17(off);
- uint16_t i;
- uint16_t bo = (off & 511);
- for (i = 0; i < bo; i++)
- SPI.transfer(0xff);
- for (i = 0; i < n; i++)
- *d++ = SPI.transfer(0xff);
- for (i = 0; i < (514 - bo - n); i++)
- SPI.transfer(0xff);
- desel();
- }
- uint32_t rd4(uint32_t off) {
- uint32_t r;
- rdn((byte*)&r, off, sizeof(r));
- return r;
- }
- uint16_t rd2(uint32_t off) {
- uint16_t r;
- rdn((byte*)&r, off, sizeof(r));
- return r;
- }
- byte rd(uint32_t off) {
- byte r;
- rdn((byte*)&r, off, sizeof(r));
- return r;
- }
- byte pin;
- byte ccs;
- byte type;
- uint16_t sectors_per_cluster;
- uint16_t reserved_sectors;
- uint16_t max_root_dir_entries;
- uint16_t sectors_per_fat;
- uint16_t cluster_size;
- uint32_t root_dir_first_cluster;
- // These are all linear addresses, hence the o_ prefix
- uint32_t o_partition;
- uint32_t o_fat;
- uint32_t o_root;
- uint32_t o_data;
- };
- static void dos83(byte dst[11], const char *ps)
- {
- byte i = 0;
- while (*ps) {
- if (*ps != '.')
- dst[i++] = toupper(*ps);
- else {
- while (i < 8)
- dst[i++] = ' ';
- }
- ps++;
- }
- while (i < 11)
- dst[i++] = ' ';
- }
- #else
- class sdcard {
- public:
- void begin(int p) {};
- };
- #endif
- ////////////////////////////////////////////////////////////////////////
- class xy {
- public:
- int x, y;
- void set(int _x, int _y);
- void rmove(int distance, int angle);
- int angleto(class xy &other);
- void draw(byte offset = 0);
- void rotate(int angle);
- int onscreen(void);
- class xy operator<<=(int d);
- class xy operator+=(class xy &other);
- class xy operator-=(class xy &other);
- long operator*(class xy &other);
- class xy operator*=(int);
- int nearer_than(int distance, xy &other);
- };
- class Bitmap {
- public:
- xy size, center;
- uint32_t source;
- uint8_t format;
- int8_t handle;
- void fromtext(int font, const char* s);
- void fromfile(const char *filename, int format = 7);
- void bind(uint8_t handle);
- void wallpaper();
- void draw(int x, int y, int16_t angle = 0);
- void draw(const xy &pos, int16_t angle = 0);
- private:
- void defaults(uint8_t f);
- void setup(void);
- };
- class Bitmap __fromatlas(uint32_t addr);
- ////////////////////////////////////////////////////////////////////////
- class GDClass {
- public:
- int w, h;
- uint32_t loadptr;
- void begin(uint8_t options = (GD_CALIBRATE | GD_TRIM | GD_STORAGE));
- uint16_t random();
- uint16_t random(uint16_t n);
- uint16_t random(uint16_t n0, uint16_t n1);
- void seed(uint16_t n);
- int16_t rsin(int16_t r, uint16_t th);
- int16_t rcos(int16_t r, uint16_t th);
- void polar(int &x, int &y, int16_t r, uint16_t th);
- uint16_t atan2(int16_t y, int16_t x);
- #if !defined(ESP8266)
- void copy(const PROGMEM uint8_t *src, int count);
- #else
- void copy(const uint8_t *src, int count);
- #endif
- void copyram(byte *src, int count);
- void self_calibrate(void);
- void swap(void);
- void flush(void);
- void finish(void);
- void play(uint8_t instrument, uint8_t note = 0);
- void sample(uint32_t start, uint32_t len, uint16_t freq, uint16_t format, int loop = 0);
- void get_inputs(void);
- void get_accel(int &x, int &y, int &z);
- struct {
- uint16_t track_tag;
- uint16_t track_val;
- uint16_t rz;
- uint16_t __dummy_1;
- int16_t y;
- int16_t x;
- int16_t tag_y;
- int16_t tag_x;
- uint8_t tag;
- uint8_t ptag;
- uint8_t touching;
- xy xytouch;
- } inputs;
- void AlphaFunc(byte func, byte ref);
- void Begin(byte prim);
- void BitmapHandle(byte handle);
- void BitmapLayout(byte format, uint16_t linestride, uint16_t height);
- void BitmapSize(byte filter, byte wrapx, byte wrapy, uint16_t width, uint16_t height);
- void BitmapSource(uint32_t addr);
- void BitmapTransformA(int32_t a);
- void BitmapTransformB(int32_t b);
- void BitmapTransformC(int32_t c);
- void BitmapTransformD(int32_t d);
- void BitmapTransformE(int32_t e);
- void BitmapTransformF(int32_t f);
- void BlendFunc(byte src, byte dst);
- void Call(uint16_t dest);
- void Cell(byte cell);
- void ClearColorA(byte alpha);
- void ClearColorRGB(byte red, byte green, byte blue);
- void ClearColorRGB(uint32_t rgb);
- void Clear(byte c, byte s, byte t);
- void Clear(void);
- void ClearStencil(byte s);
- void ClearTag(byte s);
- void ColorA(byte alpha);
- void ColorMask(byte r, byte g, byte b, byte a);
- void ColorRGB(byte red, byte green, byte blue);
- void ColorRGB(uint32_t rgb);
- void Display(void);
- void End(void);
- void Jump(uint16_t dest);
- void LineWidth(uint16_t width);
- void Macro(byte m);
- void PointSize(uint16_t size);
- void RestoreContext(void);
- void Return(void);
- void SaveContext(void);
- void ScissorSize(uint16_t width, uint16_t height);
- void ScissorXY(uint16_t x, uint16_t y);
- void StencilFunc(byte func, byte ref, byte mask);
- void StencilMask(byte mask);
- void StencilOp(byte sfail, byte spass);
- void TagMask(byte mask);
- void Tag(byte s);
- void Vertex2f(int16_t x, int16_t y);
- void Vertex2ii(uint16_t x, uint16_t y, byte handle = 0, byte cell = 0);
- void VertexFormat(byte frac);
- void BitmapLayoutH(byte linestride, byte height);
- void BitmapSizeH(byte width, byte height);
- void PaletteSource(uint32_t addr);
- void VertexTranslateX(uint32_t x);
- void VertexTranslateY(uint32_t y);
- void Nop(void);
- // Higher-level graphics commands
- void cmd_append(uint32_t ptr, uint32_t num);
- void cmd_bgcolor(uint32_t c);
- void cmd_button(int16_t x, int16_t y, uint16_t w, uint16_t h, byte font, uint16_t options, const char *s);
- void cmd_calibrate(void);
- void cmd_clock(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t h, uint16_t m, uint16_t s, uint16_t ms);
- void cmd_coldstart(void);
- void cmd_dial(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t val);
- void cmd_dlstart(void);
- void cmd_fgcolor(uint32_t c);
- void cmd_gauge(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t major, uint16_t minor, uint16_t val, uint16_t range);
- void cmd_getmatrix(void);
- void cmd_getprops(uint32_t &ptr, uint32_t &w, uint32_t &h);
- void cmd_getptr(void);
- void cmd_gradcolor(uint32_t c);
- void cmd_gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1);
- void cmd_inflate(uint32_t ptr);
- void cmd_interrupt(uint32_t ms);
- void cmd_keys(int16_t x, int16_t y, int16_t w, int16_t h, byte font, uint16_t options, const char*s);
- void cmd_loadidentity(void);
- void cmd_loadimage(uint32_t ptr, int32_t options);
- void cmd_memcpy(uint32_t dest, uint32_t src, uint32_t num);
- void cmd_memset(uint32_t ptr, byte value, uint32_t num);
- uint32_t cmd_memcrc(uint32_t ptr, uint32_t num);
- void cmd_memwrite(uint32_t ptr, uint32_t num);
- void cmd_regwrite(uint32_t ptr, uint32_t val);
- void cmd_number(int16_t x, int16_t y, byte font, uint16_t options, uint32_t n);
- void cmd_progress(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range);
- void cmd_regread(uint32_t ptr);
- void cmd_rotate(int32_t a);
- void cmd_scale(int32_t sx, int32_t sy);
- void cmd_screensaver(void);
- void cmd_scrollbar(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t size, uint16_t range);
- void cmd_setfont(byte font, uint32_t ptr);
- void cmd_setmatrix(void);
- void cmd_sketch(int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format);
- void cmd_slider(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t options, uint16_t val, uint16_t range);
- void cmd_snapshot(uint32_t ptr);
- void cmd_spinner(int16_t x, int16_t y, byte style, byte scale);
- void cmd_stop(void);
- void cmd_swap(void);
- void cmd_text(int16_t x, int16_t y, byte font, uint16_t options, const char *s);
- void cmd_toggle(int16_t x, int16_t y, int16_t w, byte font, uint16_t options, uint16_t state, const char *s);
- void cmd_track(int16_t x, int16_t y, uint16_t w, uint16_t h, byte tag);
- void cmd_translate(int32_t tx, int32_t ty);
- void cmd_playvideo(int32_t options);
- void cmd_romfont(uint32_t font, uint32_t romslot);
- void cmd_mediafifo(uint32_t ptr, uint32_t size);
- void cmd_setbase(uint32_t b);
- void cmd_videoframe(uint32_t dst, uint32_t ptr);
- void cmd_snapshot2(uint32_t fmt, uint32_t ptr, int16_t x, int16_t y, int16_t w, int16_t h);
- void cmd_setfont2(uint32_t font, uint32_t ptr, uint32_t firstchar);
- void cmd_setrotate(uint32_t r);
- void cmd_videostart();
- void cmd_setbitmap(uint32_t source, uint16_t fmt, uint16_t w, uint16_t h);
- void cmd_sync();
- byte rd(uint32_t addr);
- void wr(uint32_t addr, uint8_t v);
- uint16_t rd16(uint32_t addr);
- void wr16(uint32_t addr, uint16_t v);
- uint32_t rd32(uint32_t addr);
- void wr32(uint32_t addr, uint32_t v);
- void wr_n(uint32_t addr, byte *src, uint32_t n);
- void cmd32(uint32_t b);
- void bulkrd(uint32_t a);
- void resume(void);
- void __end(void);
- void reset(void);
- void dumpscreen(void);
- byte load(const char *filename, void (*progress)(long, long) = NULL);
- void safeload(const char *filename);
- void alert(const char *message);
- void textsize(int &w, int &h, int font, const char *s);
- sdcard SD;
- void storage(void);
- void tune(void);
- private:
- static void cFFFFFF(byte v);
- static void cI(uint32_t);
- static void ci(int32_t);
- static void cH(uint16_t);
- static void ch(int16_t);
- static void cs(const char *);
- static void fmtcmd(const char *fmt, ...);
- static void align(byte n);
- void cmdbyte(uint8_t b);
- uint32_t measure_freq(void);
- uint32_t rseed;
- };
- extern GDClass GD;
- extern byte ft8xx_model;
- #if SDCARD
- class Reader {
- public:
- int openfile(const char *filename) {
- int i = 0;
- byte dosname[11];
- dirent de;
- dos83(dosname, filename);
- do {
- GD.SD.rdn((byte*)&de, GD.SD.o_root + i * 32, sizeof(de));
- // Serial.println(de.name);
- if (0 == memcmp(de.name, dosname, 11)) {
- begin(de);
- return 1;
- }
- i++;
- } while (de.name[0]);
- return 0;
- }
- void begin(dirent &de) {
- nseq = 0;
- size = de.size;
- cluster0 = de.cluster;
- if (GD.SD.type == FAT32)
- cluster0 |= ((long)de.cluster_hi << 16);
- rewind();
- }
- void rewind(void) {
- cluster = cluster0;
- sector = 0;
- offset = 0;
- }
- void nextcluster() {
- if (GD.SD.type == FAT16)
- cluster = GD.SD.rd2(GD.SD.o_fat + 2 * cluster);
- else
- cluster = GD.SD.rd4(GD.SD.o_fat + 4 * cluster);
- #if VERBOSE
- Serial.print("nextcluster=");
- Serial.println(cluster, DEC);
- #endif
- }
- void fetch512(byte *dst) {
- #if defined(__DUE__) || defined(TEENSYDUINO) || defined(ESP8266) || 1
- #if defined(ESP8266)
- SPI.transferBytes(NULL, dst, 512);
- #else
- // for (int i = 0; i < 512; i++) *dst++ = SPI.transfer(0xff);
- memset(dst, 0xff, 512); SPI.transfer(dst, 512);
- #endif
- SPI.transfer(0xff); // consume CRC
- SPI.transfer(0xff);
- #else
- SPDR = 0xff;
- asm volatile("nop"); while (!(SPSR & _BV(SPIF))) ;
- for (int i = 0; i < 512; i++) {
- while (!(SPSR & _BV(SPIF))) ;
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- asm volatile("nop");
- *dst++ = SPDR;
- SPDR = 0xff;
- }
- asm volatile("nop"); while (!(SPSR & _BV(SPIF))) ;
- SPI.transfer(0xff);
- #endif
- GD.SD.desel();
- }
- void nextcluster2(byte *dst) {
- if (nseq) {
- nseq--;
- cluster++;
- return;
- }
- uint32_t off = GD.SD.o_fat + 4 * cluster;
- GD.SD.cmd17(off & ~511L);
- fetch512(dst);
- int i = off & 511;
- cluster = *(uint32_t*)&dst[i];
- nseq = 0;
- for (uint32_t c = cluster;
- (i < 512) && *(uint32_t*)&dst[i] == c;
- i += 4, c++)
- nseq++;
- }
- void skipcluster() {
- nextcluster();
- offset += GD.SD.cluster_size;
- }
- void skipsector() {
- if (sector == GD.SD.sectors_per_cluster) {
- sector = 0;
- nextcluster();
- }
- sector++;
- offset += 512;
- }
- void seek(uint32_t o) {
- union {
- uint8_t buf[512];
- uint32_t fat32[128];
- uint16_t fat16[256];
- };
- uint32_t co = ~0;
- if (o < offset)
- rewind();
- while (offset < o) {
- if ((sector == GD.SD.sectors_per_cluster) && ((o - offset) > (long)GD.SD.cluster_size)) {
- uint32_t o;
- if (GD.SD.type == FAT16)
- o = (GD.SD.o_fat + 2 * cluster) & ~511;
- else
- o = (GD.SD.o_fat + 4 * cluster) & ~511;
- if (o != co) {
- GD.SD.rdn(buf, o, 512);
- co = o;
- }
- cluster = fat32[cluster & 127];
- offset += GD.SD.cluster_size;
- } else
- skipsector();
- }
- }
- void readsector(byte *dst) {
- if (sector == GD.SD.sectors_per_cluster) {
- sector = 0;
- nextcluster2(dst);
- }
- REPORT(cluster);
- uint32_t off = GD.SD.o_data + ((long)GD.SD.cluster_size * cluster) + (512L * sector);
- REPORT(off);
- GD.SD.cmd17(off & ~511L);
- REPORT(off);
- sector++;
- offset += 512;
- fetch512(dst);
- }
- int eof(void) {
- return size <= offset;
- }
- uint32_t cluster, cluster0;
- uint32_t offset;
- uint32_t size;
- byte sector;
- byte nseq;
- };
- #endif
- typedef struct {
- byte handle;
- uint16_t w, h;
- uint16_t size;
- } shape_t;
- // convert integer pixels to subpixels
- #define PIXELS(x) int((x) * 16)
- // Convert degrees to Furmans
- #define DEGREES(n) ((65536L * (n)) / 360)
- #define NEVER 0
- #define LESS 1
- #define LEQUAL 2
- #define GREATER 3
- #define GEQUAL 4
- #define EQUAL 5
- #define NOTEQUAL 6
- #define ALWAYS 7
- #define ARGB1555 0
- #define L1 1
- #define L4 2
- #define L8 3
- #define RGB332 4
- #define ARGB2 5
- #define ARGB4 6
- #define RGB565 7
- #define PALETTED 8
- #define TEXT8X8 9
- #define TEXTVGA 10
- #define BARGRAPH 11
- #define L2 17
- #define NEAREST 0
- #define BILINEAR 1
- #define BORDER 0
- #define REPEAT 1
- #define KEEP 1
- #define REPLACE 2
- #define INCR 3
- #define DECR 4
- #define INVERT 5
- #define DLSWAP_DONE 0
- #define DLSWAP_LINE 1
- #define DLSWAP_FRAME 2
- #define INT_SWAP 1
- #define INT_TOUCH 2
- #define INT_TAG 4
- #define INT_SOUND 8
- #define INT_PLAYBACK 16
- #define INT_CMDEMPTY 32
- #define INT_CMDFLAG 64
- #define INT_CONVCOMPLETE 128
- #define TOUCHMODE_OFF 0
- #define TOUCHMODE_ONESHOT 1
- #define TOUCHMODE_FRAME 2
- #define TOUCHMODE_CONTINUOUS 3
- #define ZERO 0
- #define ONE 1
- #define SRC_ALPHA 2
- #define DST_ALPHA 3
- #define ONE_MINUS_SRC_ALPHA 4
- #define ONE_MINUS_DST_ALPHA 5
- #define BITMAPS 1
- #define POINTS 2
- #define LINES 3
- #define LINE_STRIP 4
- #define EDGE_STRIP_R 5
- #define EDGE_STRIP_L 6
- #define EDGE_STRIP_A 7
- #define EDGE_STRIP_B 8
- #define RECTS 9
- #define OPT_MONO 1
- #define OPT_NODL 2
- #define OPT_FLAT 256
- #define OPT_CENTERX 512
- #define OPT_CENTERY 1024
- #define OPT_CENTER (OPT_CENTERX | OPT_CENTERY)
- #define OPT_NOBACK 4096
- #define OPT_NOTICKS 8192
- #define OPT_NOHM 16384
- #define OPT_NOPOINTER 16384
- #define OPT_NOSECS 32768
- #define OPT_NOHANDS 49152
- #define OPT_RIGHTX 2048
- #define OPT_SIGNED 256
- #define OPT_SOUND 32
- #define OPT_NOTEAR 4
- #define OPT_FULLSCREEN 8
- #define OPT_MEDIAFIFO 16
- #define LINEAR_SAMPLES 0
- #define ULAW_SAMPLES 1
- #define ADPCM_SAMPLES 2
- // 'instrument' argument to GD.play()
- #define SILENCE 0x00
- #define SQUAREWAVE 0x01
- #define SINEWAVE 0x02
- #define SAWTOOTH 0x03
- #define TRIANGLE 0x04
- #define BEEPING 0x05
- #define ALARM 0x06
- #define WARBLE 0x07
- #define CAROUSEL 0x08
- #define PIPS(n) (0x0f + (n))
- #define HARP 0x40
- #define XYLOPHONE 0x41
- #define TUBA 0x42
- #define GLOCKENSPIEL 0x43
- #define ORGAN 0x44
- #define TRUMPET 0x45
- #define PIANO 0x46
- #define CHIMES 0x47
- #define MUSICBOX 0x48
- #define BELL 0x49
- #define CLICK 0x50
- #define SWITCH 0x51
- #define COWBELL 0x52
- #define NOTCH 0x53
- #define HIHAT 0x54
- #define KICKDRUM 0x55
- #define POP 0x56
- #define CLACK 0x57
- #define CHACK 0x58
- #define MUTE 0x60
- #define UNMUTE 0x61
- #define RAM_PAL 1056768UL
- #define RAM_CMD (ft8xx_model ? 0x308000UL : 0x108000UL)
- #define RAM_DL (ft8xx_model ? 0x300000UL : 0x100000UL)
- #define REG_CLOCK (ft8xx_model ? 0x302008UL : 0x102408UL)
- #define REG_CMD_DL (ft8xx_model ? 0x302100UL : 0x1024ecUL)
- #define REG_CMD_READ (ft8xx_model ? 0x3020f8UL : 0x1024e4UL)
- #define REG_CMD_WRITE (ft8xx_model ? 0x3020fcUL : 0x1024e8UL)
- #define REG_CPURESET (ft8xx_model ? 0x302020UL : 0x10241cUL)
- #define REG_CSPREAD (ft8xx_model ? 0x302068UL : 0x102464UL)
- #define REG_DITHER (ft8xx_model ? 0x302060UL : 0x10245cUL)
- #define REG_DLSWAP (ft8xx_model ? 0x302054UL : 0x102450UL)
- #define REG_FRAMES (ft8xx_model ? 0x302004UL : 0x102404UL)
- #define REG_FREQUENCY (ft8xx_model ? 0x30200cUL : 0x10240cUL)
- #define REG_GPIO (ft8xx_model ? 0x302094UL : 0x102490UL)
- #define REG_GPIO_DIR (ft8xx_model ? 0x302090UL : 0x10248cUL)
- #define REG_HCYCLE (ft8xx_model ? 0x30202cUL : 0x102428UL)
- #define REG_HOFFSET (ft8xx_model ? 0x302030UL : 0x10242cUL)
- #define REG_HSIZE (ft8xx_model ? 0x302034UL : 0x102430UL)
- #define REG_HSYNC0 (ft8xx_model ? 0x302038UL : 0x102434UL)
- #define REG_HSYNC1 (ft8xx_model ? 0x30203cUL : 0x102438UL)
- #define REG_ID (ft8xx_model ? 0x302000UL : 0x102400UL)
- #define REG_INT_EN (ft8xx_model ? 0x3020acUL : 0x10249cUL)
- #define REG_INT_FLAGS (ft8xx_model ? 0x3020a8UL : 0x102498UL)
- #define REG_INT_MASK (ft8xx_model ? 0x3020b0UL : 0x1024a0UL)
- #define REG_MACRO_0 (ft8xx_model ? 0x3020d8UL : 0x1024c8UL)
- #define REG_MACRO_1 (ft8xx_model ? 0x3020dcUL : 0x1024ccUL)
- #define REG_OUTBITS (ft8xx_model ? 0x30205cUL : 0x102458UL)
- #define REG_PCLK (ft8xx_model ? 0x302070UL : 0x10246cUL)
- #define REG_PCLK_POL (ft8xx_model ? 0x30206cUL : 0x102468UL)
- #define REG_PLAY (ft8xx_model ? 0x30208cUL : 0x102488UL)
- #define REG_PLAYBACK_FORMAT (ft8xx_model ? 0x3020c4UL : 0x1024b4UL)
- #define REG_PLAYBACK_FREQ (ft8xx_model ? 0x3020c0UL : 0x1024b0UL)
- #define REG_PLAYBACK_LENGTH (ft8xx_model ? 0x3020b8UL : 0x1024a8UL)
- #define REG_PLAYBACK_LOOP (ft8xx_model ? 0x3020c8UL : 0x1024b8UL)
- #define REG_PLAYBACK_PLAY (ft8xx_model ? 0x3020ccUL : 0x1024bcUL)
- #define REG_PLAYBACK_READPTR (ft8xx_model ? 0x3020bcUL : 0x1024acUL)
- #define REG_PLAYBACK_START (ft8xx_model ? 0x3020b4UL : 0x1024a4UL)
- #define REG_PWM_DUTY (ft8xx_model ? 0x3020d4UL : 0x1024c4UL)
- #define REG_PWM_HZ (ft8xx_model ? 0x3020d0UL : 0x1024c0UL)
- #define REG_ROTATE (ft8xx_model ? 0x302058UL : 0x102454UL)
- #define REG_SOUND (ft8xx_model ? 0x302088UL : 0x102484UL)
- #define REG_SWIZZLE (ft8xx_model ? 0x302064UL : 0x102460UL)
- #define REG_TAG (ft8xx_model ? 0x30207cUL : 0x102478UL)
- #define REG_TAG_X (ft8xx_model ? 0x302074UL : 0x102470UL)
- #define REG_TAG_Y (ft8xx_model ? 0x302078UL : 0x102474UL)
- #define REG_TOUCH_ADC_MODE (ft8xx_model ? 0x302108UL : 0x1024f4UL)
- #define REG_TOUCH_CHARGE (ft8xx_model ? 0x30210cUL : 0x1024f8UL)
- #define REG_TOUCH_DIRECT_XY (ft8xx_model ? 0x30218cUL : 0x102574UL)
- #define REG_TOUCH_DIRECT_Z1Z2 (ft8xx_model ? 0x302190UL : 0x102578UL)
- #define REG_TOUCH_MODE (ft8xx_model ? 0x302104UL : 0x1024f0UL)
- #define REG_TOUCH_OVERSAMPLE (ft8xx_model ? 0x302114UL : 0x102500UL)
- #define REG_TOUCH_RAW_XY (ft8xx_model ? 0x30211cUL : 0x102508UL)
- #define REG_TOUCH_RZ (ft8xx_model ? 0x302120UL : 0x10250cUL)
- #define REG_TOUCH_RZTHRESH (ft8xx_model ? 0x302118UL : 0x102504UL)
- #define REG_TOUCH_SCREEN_XY (ft8xx_model ? 0x302124UL : 0x102510UL)
- #define REG_TOUCH_SETTLE (ft8xx_model ? 0x302110UL : 0x1024fcUL)
- #define REG_TOUCH_TAG (ft8xx_model ? 0x30212cUL : 0x102518UL)
- #define REG_TOUCH_TAG_XY (ft8xx_model ? 0x302128UL : 0x102514UL)
- #define REG_TOUCH_TRANSFORM_A (ft8xx_model ? 0x302150UL : 0x10251cUL)
- #define REG_TOUCH_TRANSFORM_B (ft8xx_model ? 0x302154UL : 0x102520UL)
- #define REG_TOUCH_TRANSFORM_C (ft8xx_model ? 0x302158UL : 0x102524UL)
- #define REG_TOUCH_TRANSFORM_D (ft8xx_model ? 0x30215cUL : 0x102528UL)
- #define REG_TOUCH_TRANSFORM_E (ft8xx_model ? 0x302160UL : 0x10252cUL)
- #define REG_TOUCH_TRANSFORM_F (ft8xx_model ? 0x302164UL : 0x102530UL)
- #define REG_TRACKER (ft8xx_model ? 0x309000UL : 0x109000UL)
- #define REG_TRIM (ft8xx_model ? 0x302180UL : 0x10256cUL)
- #define REG_VCYCLE (ft8xx_model ? 0x302040UL : 0x10243cUL)
- #define REG_VOFFSET (ft8xx_model ? 0x302044UL : 0x102440UL)
- #define REG_VOL_PB (ft8xx_model ? 0x302080UL : 0x10247cUL)
- #define REG_VOL_SOUND (ft8xx_model ? 0x302084UL : 0x102480UL)
- #define REG_VSIZE (ft8xx_model ? 0x302048UL : 0x102444UL)
- #define REG_VSYNC0 (ft8xx_model ? 0x30204cUL : 0x102448UL)
- #define REG_VSYNC1 (ft8xx_model ? 0x302050UL : 0x10244cUL)
- #define FONT_ROOT (ft8xx_model ? 0x2ffffcUL : 0x0ffffcUL)
- #define REG_MEDIAFIFO_READ 0x309014
- #define REG_MEDIAFIFO_WRITE 0x309018
- #define VERTEX2II(x, y, handle, cell) \
- ((2UL << 30) | (((x) & 511UL) << 21) | (((y) & 511UL) << 12) | (((handle) & 31) << 7) | (((cell) & 127) << 0))
- #define ROM_PIXEL_FF 0xc0400UL
- class Poly {
- int x0, y0, x1, y1;
- int x[8], y[8];
- byte n;
- void restart() {
- n = 0;
- x0 = 16 * 480;
- x1 = 0;
- y0 = 16 * 272;
- y1 = 0;
- }
- void perim() {
- for (byte i = 0; i < n; i++)
- GD.Vertex2f(x[i], y[i]);
- GD.Vertex2f(x[0], y[0]);
- }
- public:
- void begin() {
- restart();
- GD.ColorMask(0,0,0,0);
- GD.StencilOp(KEEP, INVERT);
- GD.StencilFunc(ALWAYS, 255, 255);
- }
- void v(int _x, int _y) {
- x0 = min(x0, _x >> 4);
- x1 = max(x1, _x >> 4);
- y0 = min(y0, _y >> 4);
- y1 = max(y1, _y >> 4);
- x[n] = _x;
- y[n] = _y;
- n++;
- }
- void paint() {
- x0 = max(0, x0);
- y0 = max(0, y0);
- x1 = min(16 * 480, x1);
- y1 = min(16 * 272, y1);
- GD.ScissorXY(x0, y0);
- GD.ScissorSize(x1 - x0 + 1, y1 - y0 + 1);
- GD.Begin(EDGE_STRIP_B);
- perim();
- }
- void finish() {
- GD.ColorMask(1,1,1,1);
- GD.StencilFunc(EQUAL, 255, 255);
- GD.Begin(EDGE_STRIP_B);
- GD.Vertex2ii(0, 0);
- GD.Vertex2ii(511, 0);
- }
- void draw() {
- paint();
- finish();
- }
- void outline() {
- GD.Begin(LINE_STRIP);
- perim();
- }
- };
- #if SDCARD
- class Streamer {
- public:
- void begin(const char *rawsamples,
- uint16_t freq = 44100,
- byte format = ADPCM_SAMPLES,
- uint32_t _base = (0x40000UL - 8192), uint16_t size = 8192) {
- GD.__end();
- r.openfile(rawsamples);
- GD.resume();
- base = _base;
- mask = size - 1;
- wp = 0;
- for (byte i = 10; i; i--)
- feed();
- GD.sample(base, size, freq, format, 1);
- }
- int feed() {
- uint16_t rp = GD.rd32(REG_PLAYBACK_READPTR) - base;
- uint16_t freespace = mask & ((rp - 1) - wp);
- if (freespace >= 512) {
- // REPORT(base);
- // REPORT(rp);
- // REPORT(wp);
- // REPORT(freespace);
- // Serial.println();
- byte buf[512];
- // uint16_t n = min(512, r.size - r.offset);
- // n = (n + 3) & ~3; // force 32-bit alignment
- GD.__end();
- r.readsector(buf);
- GD.resume();
- GD.cmd_memwrite(base + wp, 512);
- GD.copyram(buf, 512);
- wp = (wp + 512) & mask;
- }
- return r.offset < r.size;
- }
- void progress(uint16_t &val, uint16_t &range) {
- uint32_t m = r.size;
- uint32_t p = min(r.offset, m);
- while (m > 0x10000) {
- m >>= 1;
- p >>= 1;
- }
- val = p;
- range = m;
- }
- private:
- Reader r;
- uint32_t base;
- uint16_t mask;
- uint16_t wp;
- };
- #else
- class Streamer {
- public:
- void begin(const char *rawsamples,
- uint16_t freq = 44100,
- byte format = ADPCM_SAMPLES,
- uint32_t _base = (0x40000UL - 4096), uint16_t size = 4096) {}
- int feed() {}
- void progress(uint16_t &val, uint16_t &range) {}
- };
- #endif
- ////////////////////////////////////////////////////////////////////////
- // TileMap: maps made with the "tiled" map editor
- ////////////////////////////////////////////////////////////////////////
- class TileMap {
- uint32_t chunkstart;
- int chunkw, chunkh;
- int stride;
- int bpc;
- byte layers;
- public:
- uint16_t w, h;
- void begin(uint32_t loadpoint) {
- GD.finish();
- w = GD.rd16(loadpoint + 0);
- h = GD.rd16(loadpoint + 2);
- chunkw = GD.rd16(loadpoint + 4);
- chunkh = GD.rd16(loadpoint + 6);
- stride = GD.rd16(loadpoint + 8);
- layers = GD.rd16(loadpoint + 10);
- bpc = (4 * 16);
- chunkstart = loadpoint + 12;
- }
- void draw(uint16_t x, uint16_t y, uint16_t layermask = ~0) {
- int16_t chunk_x = (x / chunkw);
- int16_t ox0 = -(x % chunkw);
- int16_t chunk_y = (y / chunkh);
- int16_t oy = -(y % chunkh);
- GD.Begin(BITMAPS);
- GD.SaveContext();
- GD.BlendFunc(ONE, ONE_MINUS_SRC_ALPHA);
- while (oy < GD.h) {
- int16_t ox = ox0;
- GD.VertexTranslateY(oy << 4);
- uint32_t pos = chunkstart + (chunk_x + long(stride) * chunk_y) * layers * bpc;
- while (ox < GD.w) {
- GD.VertexTranslateX(ox << 4);
- for (byte layer = 0; layer < layers; layer++)
- if (layermask & (1 << layer))
- GD.cmd_append(pos + bpc * layer, bpc);
- pos += (layers * bpc);
- ox += chunkw;
- }
- oy += chunkh;
- chunk_y++;
- }
- GD.RestoreContext();
- }
- void draw(xy pos) {
- draw(pos.x >> 4, pos.y >> 4);
- }
- uint32_t addr(uint16_t x, uint16_t y, byte layer) {
- int16_t tx = (x / (chunkw >> 2));
- int16_t ty = (y / (chunkh >> 2));
- return
- chunkstart +
- ((tx >> 2) + long(stride) * (ty >> 2)) * layers * bpc +
- (tx & 3) * 4 +
- (ty & 3) * 16 +
- layer * 64;
- }
- int read(uint16_t x, uint16_t y, byte layer) {
- uint32_t op = GD.rd32(addr(x, y, layer));
- if ((op >> 24) == 0x2d)
- return 0;
- else
- return 1 + (op & 2047);
- }
- void write(uint16_t x, uint16_t y, byte layer, int tile) {
- uint32_t op;
- uint32_t a = addr(x, y, layer);
- if (tile == 0)
- op = 0x2d000000UL;
- else
- op = (GD.rd32(a) & ~2047) | ((tile - 1) & 2047);
- GD.wr32(a, op);
- }
- int read(xy pos, byte layer) {
- return read(pos.x >> 4, pos.y >> 4, layer);
- }
- void write(xy pos, byte layer, int tile) {
- write(pos.x >> 4, pos.y >> 4, layer, tile);
- }
- };
- class MoviePlayer
- {
- uint32_t mf_size, mf_base, wp;
- Reader r;
- void loadsector() {
- byte buf[512];
- GD.__end();
- r.readsector(buf);
- GD.resume();
- GD.wr_n(mf_base + wp, buf, 512);
- wp = (wp + 512) & (mf_size - 1);
- }
- public:
- int begin(const char *filename) {
- mf_size = 0x40000UL;
- mf_base = 0x100000UL - mf_size;
- GD.__end();
- if (!r.openfile(filename)) {
- // Serial.println("Open failed");
- return 0;
- }
- GD.resume();
- wp = 0;
- while (wp < (mf_size - 512)) {
- loadsector();
- }
- GD.cmd_mediafifo(mf_base, mf_size);
- GD.cmd_regwrite(REG_MEDIAFIFO_WRITE, wp);
- GD.finish();
- return 1;
- }
- int service() {
- if (r.eof()) {
- return 0;
- } else {
- byte buf[512];
- uint32_t fullness = (wp - GD.rd32(REG_MEDIAFIFO_READ)) & (mf_size - 1);
- while (fullness < (mf_size - 512)) {
- loadsector();
- fullness += 512;
- GD.wr32(REG_MEDIAFIFO_WRITE, wp);
- }
- return 1;
- }
- }
- void play() {
- GD.cmd_playvideo(OPT_MEDIAFIFO | OPT_FULLSCREEN);
- GD.flush();
- while (service())
- ;
- GD.cmd_memcpy(0, 0, 4);
- GD.finish();
- }
- };
- class Dirsearch {
- struct dirent de;
- int index;
-
- public:
- char name[13];
- void begin() {
- index = 0;
- }
- int get(const char *ext) {
- byte i;
- GD.__end();
- char e3[3];
- do {
- GD.SD.rdn((byte*)&de, GD.SD.o_root + index++ * 32, sizeof(de));
- for (i = 0; i < 3; i++)
- e3[i] = tolower(de.ext[i]);
- } while (de.name[0] &&
- ((de.name[0] & 0x80) || (memcmp(ext, e3, 3) != 0)));
- GD.resume();
- char *pc = name;
- for (i = 0; i < 8 && de.name[i] != ' '; i++)
- *pc++ = tolower(de.name[i]);
- *pc++ = '.';
- for (i = 0; i < 3 && de.ext[i] != ' '; i++)
- *pc++ = tolower(de.ext[i]);
- *pc++ = 0;
- return de.name[0];
- }
- };
- /*
- * PROGMEM declarations are currently not supported by the ESP8266
- * compiler. So redefine PROGMEM to nothing.
- */
- #if defined(ESP8266) || defined(ARDUINO_ARCH_STM32L4)
- #undef PROGMEM
- #define PROGMEM
- #endif
- #endif
|