Library(Beta) for Gameduino 2
Diff: GD2.cpp
- Revision:
- 0:9c211972beb2
diff -r 000000000000 -r 9c211972beb2 GD2.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GD2.cpp Fri Apr 11 07:24:23 2014 +0000 @@ -0,0 +1,825 @@ +#include "stdarg.h" +#include "GD2.h" +#include "Utils.h" + +//AnalogIn accel[3] = {P0_23, P0_24, P0_25}; +byte touch_transform0[] = { 0xEA, 0x81, 0x00, 0x00, 0xAE, 0xFE, 0xFF, 0xFF, 0x49, 0xCC, 0xEC, 0xFF, 0x28, 0x00, 0x00, 0x00, 0x09, 0xB3, 0xFF, 0xFF, 0x42, 0x5D, 0x18, 0x01 }; +byte touch_transform1[] = { 0xAB, 0x7E, 0xFF, 0xFF, 0x0F, 0x01, 0x00, 0x00, 0x97, 0x22, 0xEE, 0x01, 0xA3, 0x00, 0x00, 0x00, 0xB3, 0x4B, 0x00, 0x00, 0xE9, 0xC9, 0xF6, 0xFF }; + +GDClass::GDClass(PinName mosi, PinName miso, PinName sclk, PinName graphic_cs, PinName sdcard_cs) + : GDTR(mosi, miso, sclk, graphic_cs) +{ + _sdcard_cs = sdcard_cs; + + accel[0] = new AnalogIn(P0_23); + accel[1] = new AnalogIn(P0_24); + accel[2] = new AnalogIn(P0_25); +} + +void GDClass::begin(uint8_t options) +{ + GDTR.begin(); + + // Generate a blank screen + cmd_dlstart(); + Clear(); + swap(); + finish(); + + GDTR.wr(REG_PCLK_POL, 1); + + GDTR.wr(REG_PCLK, 5); +#if PROTO == 1 + GDTR.wr(REG_ROTATE, 0); + GDTR.wr(REG_SWIZZLE, 3); +#endif + GDTR.wr(REG_GPIO_DIR, 0x83); + GDTR.wr(REG_GPIO, 0x80); + + for (int i = 0; i < sizeof(touch_transform0); i++) + { + if(GDTR.rd(REG_ROTATE) == 0) + GDTR.wr(REG_TOUCH_TRANSFORM_A + i, touch_transform0[i]); + else + GDTR.wr(REG_TOUCH_TRANSFORM_A + i, touch_transform1[i]); + } + + if (options & GD_CALIBRATE) + { +#if CALIBRATION + + self_calibrate(); + for (int i = 0; i < 24; i++) + std::printf("0x%02X, ", GDTR.rd(REG_TOUCH_TRANSFORM_A + i)); +/* + if (EEPROM.read(0) != 0x7c) { + self_calibrate(); + for (int i = 0; i < 24; i++) + DEBUGOUT(GDTR.rd(REG_TOUCH_TRANSFORM_A + i), HEX); + for (int i = 0; i < 24; i++) + EEPROM.write(1 + i, GDTR.rd(REG_TOUCH_TRANSFORM_A + i)); + EEPROM.write(0, 0x7c); // is written! + } else { + for (int i = 0; i < 24; i++) + GDTR.wr(REG_TOUCH_TRANSFORM_A + i, EEPROM.read(1 + i)); + } +*/ +#endif + } + + GDTR.wr16(REG_TOUCH_RZTHRESH, 1200); + + lfsr = 0x5555; + lcg = 0; + + SD = new sdcard(GDTR.SPI(), _sdcard_cs); + +#if STORAGE + if (options & GD_STORAGE) + { + storage(); + } +#endif + + if (options & GD_TRIM) + { + tune(); + DEBUGOUT("tune()\r\n"); + } +} + +void GDClass::flush(void) +{ + GDTR.flush(); +} + +void GDClass::swap(void) { + Display(); + cmd_swap(); + cmd_loadidentity(); + cmd_dlstart(); + GDTR.flush(); +} + +uint32_t GDClass::measure_freq(void) +{ + unsigned long t0 = GDTR.rd32(REG_CLOCK); + delayMicroseconds(15625); + unsigned long t1 = GDTR.rd32(REG_CLOCK); + return (t1 - t0) << 6; +} + +void GDClass::tune(void) +{ + uint32_t f; + for (byte i = 0; (i < 31) && ((f = measure_freq()) < LOW_FREQ_BOUND); i++) + GDTR.wr(REG_TRIM, i); + GDTR.wr32(REG_FREQUENCY, f); +} + + +void GDClass::storage(void) { + GDTR.__end(); + SD->begin(); + GDTR.resume(); +} + +void GDClass::self_calibrate(void) { + cmd_dlstart(); + Clear(); + cmd_text(240, 100, 30, OPT_CENTERX, "please tap on the dot"); + cmd_calibrate(); + finish(); + cmd_loadidentity(); + cmd_dlstart(); + GDTR.flush(); +} + +void GDClass::seed(uint16_t n) { + lfsr = n | 1; + lcg = n ^ 0x7921; +} +uint16_t GDClass::random() { + lfsr = (lfsr >> 1) ^ (-(lfsr & 1u) & 0xB400u); + lcg = (lcg * 47) + 60497; + return (lcg ^ lfsr); +} +uint16_t GDClass::random(uint16_t n) { + return GDClass::random() % n; +} + + +// >>> [int(65535*math.sin(math.pi * 2 * i / 1024)) for i in range(257)] +static PROGMEM int sintab[257] = { + 0, 402, 804, 1206, 1608, 2010, 2412, 2813, 3215, 3617, 4018, 4419, 4821, 5221, 5622, 6023, 6423, 6823, 7223, 7622, 8022, 8421, 8819, 9218, 9615, 10013, 10410, 10807, 11203, 11599, 11995, 12390, 12785, 13179, 13573, 13966, 14358, 14750, 15142, 15533, 15923, 16313, 16702, 17091, 17479, 17866, 18252, 18638, 19023, 19408, 19791, 20174, 20557, 20938, 21319, 21699, 22078, 22456, 22833, 23210, 23585, 23960, 24334, 24707, 25079, 25450, 25820, 26189, 26557, 26924, 27290, 27655, 28019, 28382, 28744, 29105, 29465, 29823, 30181, 30537, 30892, 31247, 31599, 31951, 32302, 32651, 32999, 33346, 33691, 34035, 34378, 34720, 35061, 35400, 35737, 36074, 36409, 36742, 37075, 37406, 37735, 38063, 38390, 38715, 39039, 39361, 39682, 40001, 40319, 40635, 40950, 41263, 41574, 41885, 42193, 42500, 42805, 43109, 43411, 43711, 44010, 44307, 44603, 44896, 45189, 45479, 45768, 46055, 46340, 46623, 46905, 47185, 47463, 47739, 48014, 48287, 48558, 48827, 49094, 49360, 49623, 49885, 50145, 50403, 50659, 50913, 51165, 51415, 51664, 51910, 52155, 52397, 52638, 52876, 53113, 53347, 53580, 53810, 54039, 54265, 54490, 54712, 54933, 55151, 55367, 55581, 55793, 56003, 56211, 56416, 56620, 56821, 57021, 57218, 57413, 57606, 57796, 57985, 58171, 58355, 58537, 58717, 58894, 59069, 59242, 59413, 59582, 59748, 59912, 60074, 60234, 60391, 60546, 60699, 60849, 60997, 61143, 61287, 61428, 61567, 61704, 61838, 61970, 62100, 62227, 62352, 62474, 62595, 62713, 62828, 62941, 63052, 63161, 63267, 63370, 63472, 63570, 63667, 63761, 63853, 63942, 64029, 64114, 64196, 64275, 64353, 64427, 64500, 64570, 64637, 64702, 64765, 64825, 64883, 64938, 64991, 65042, 65090, 65135, 65178, 65219, 65257, 65293, 65326, 65357, 65385, 65411, 65435, 65456, 65474, 65490, 65504, 65515, 65523, 65530, 65533, 65535 +}; + +int16_t GDClass::rsin(int16_t r, uint16_t th) { + th >>= 6; // angle 0-123 + // return int(r * sin((2 * M_PI) * th / 1024.)); + int th4 = th & 511; + if (th4 & 256) + th4 = 512 - th4; // 256->256 257->255, etc + uint16_t s = pgm_read_word_near(sintab + th4); + int16_t p = ((uint32_t)s * r) >> 16; + if (th & 512) + p = -p; + return p; +} + +int16_t GDClass::rcos(int16_t r, uint16_t th) { + return rsin(r, th + 0x4000); +} + +void GDClass::polar(int &x, int &y, int16_t r, uint16_t th) { + x = (int)(-rsin(r, th)); + y = (int)( rcos(r, th)); +} + +// >>> [int(round(1024 * math.atan(i / 256.) / math.pi)) for i in range(256)] +static PROGMEM unsigned char atan8[] = { + 0,1,3,4,5,6,8,9,10,11,13,14,15,17,18,19,20,22,23,24,25,27,28,29,30,32,33,34,36,37,38,39,41,42,43,44,46,47,48,49,51,52,53,54,55,57,58,59,60,62,63,64,65,67,68,69,70,71,73,74,75,76,77,79,80,81,82,83,85,86,87,88,89,91,92,93,94,95,96,98,99,100,101,102,103,104,106,107,108,109,110,111,112,114,115,116,117,118,119,120,121,122,124,125,126,127,128,129,130,131,132,133,134,135,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,177,178,179,180,181,182,183,184,185,186,187,188,188,189,190,191,192,193,194,195,195,196,197,198,199,200,201,201,202,203,204,205,206,206,207,208,209,210,211,211,212,213,214,215,215,216,217,218,219,219,220,221,222,222,223,224,225,225,226,227,228,228,229,230,231,231,232,233,234,234,235,236,236,237,238,239,239,240,241,241,242,243,243,244,245,245,246,247,248,248,249,250,250,251,251,252,253,253,254,255,255 +}; + +uint16_t GDClass::atan2(int16_t y, int16_t x) +{ + uint16_t a; + uint16_t xx = 0; + + if ((x <= 0) ^ (y > 0)) { + int16_t t; t = x; x = y; y = t; + xx ^= 0x4000; + } + if (x <= 0) { + x = -x; + } else { + xx ^= 0x8000; + } + y = abs(y); + if (x > y) { + int16_t t; t = x; x = y; y = t; + xx ^= 0x3fff; + } + while ((x | y) & 0xff80) { + x >>= 1; + y >>= 1; + } + if (y == 0) { + a = 0; + } else if (x == y) { + a = 0x2000; + } else { + // assert(x <= y); + int r = ((x << 8) / y); + // assert(0 <= r); + // assert(r < 256); + a = pgm_read_byte(atan8 + r) << 5; + } + a ^= xx; + return a; +} + +void GDClass::align(byte n) { + while ((n++) & 3) + GDTR.cmdbyte(0); +} + +void GDClass::cH(uint16_t v) { + GDTR.cmdbyte(v & 0xff); + GDTR.cmdbyte((v >> 8) & 0xff); +} + +void GDClass::ch(int16_t v) { + cH((uint16_t)v); +} + +void GDClass::cI(uint32_t v) { + GDTR.cmd32(v); +} + +void GDClass::cFFFFFF(byte v) { + union { + uint32_t c; + uint8_t b[4]; + }; + b[0] = v; + b[1] = 0xff; + b[2] = 0xff; + b[3] = 0xff; + GDTR.cmd32(c); +} + +void GDClass::ci(int32_t v) { + cI((uint32_t) v); +} + +void GDClass::cs(const char *s) { + while (*s) { + char c = *s++; + GDTR.cmdbyte(c); + } + GDTR.cmdbyte(0); +} + +void GDClass::copy(const unsigned char *src, int count) { + byte a = count & 3; + while (count--) { + GDTR.cmdbyte(pgm_read_byte_near(src)); + src++; + } + align(a); +} + +void GDClass::copyram(byte *src, int count) { + byte a = count & 3; + GDTR.cmd_n(src, count); + align(a); +} + +void GDClass::AlphaFunc(byte func, byte ref) { + cI((9UL << 24) | ((func & 7L) << 8) | ((ref & 255L) << 0)); +} +void GDClass::Begin(byte prim) { + cI((31UL << 24) | prim); +} +void GDClass::BitmapHandle(byte handle) { + cI((5UL << 24) | handle); +} +void GDClass::BitmapLayout(byte format, uint16_t linestride, uint16_t height) { + // cI((7UL << 24) | ((format & 31L) << 19) | ((linestride & 1023L) << 9) | ((height & 511L) << 0)); + union { + uint32_t c; + uint8_t b[4]; + }; + b[0] = height; + b[1] = (1 & (height >> 8)) | (linestride << 1); + b[2] = (7 & (linestride >> 7)) | (format << 3); + b[3] = 7; + cI(c); +} +void GDClass::BitmapSize(byte filter, byte wrapx, byte wrapy, uint16_t width, uint16_t height) { + byte fxy = (filter << 2) | (wrapx << 1) | (wrapy); + // cI((8UL << 24) | ((uint32_t)fxy << 18) | ((width & 511L) << 9) | ((height & 511L) << 0)); + union { + uint32_t c; + uint8_t b[4]; + }; + b[0] = height; + b[1] = (1 & (height >> 8)) | (width << 1); + b[2] = (3 & (width >> 7)) | (fxy << 2); + b[3] = 8; + cI(c); +} +void GDClass::BitmapSource(uint32_t addr) { + cI((1UL << 24) | ((addr & 1048575L) << 0)); +} +void GDClass::BitmapTransformA(int32_t a) { + cI((21UL << 24) | ((a & 131071L) << 0)); +} +void GDClass::BitmapTransformB(int32_t b) { + cI((22UL << 24) | ((b & 131071L) << 0)); +} +void GDClass::BitmapTransformC(int32_t c) { + cI((23UL << 24) | ((c & 16777215L) << 0)); +} +void GDClass::BitmapTransformD(int32_t d) { + cI((24UL << 24) | ((d & 131071L) << 0)); +} +void GDClass::BitmapTransformE(int32_t e) { + cI((25UL << 24) | ((e & 131071L) << 0)); +} +void GDClass::BitmapTransformF(int32_t f) { + cI((26UL << 24) | ((f & 16777215L) << 0)); +} +void GDClass::BlendFunc(byte src, byte dst) { + cI((11UL << 24) | ((src & 7L) << 3) | ((dst & 7L) << 0)); +} +void GDClass::Call(uint16_t dest) { + cI((29UL << 24) | ((dest & 2047L) << 0)); +} +void GDClass::Cell(byte cell) { + cI((6UL << 24) | ((cell & 127L) << 0)); +} +void GDClass::ClearColorA(byte alpha) { + cI((15UL << 24) | ((alpha & 255L) << 0)); +} +void GDClass::ClearColorRGB(byte red, byte green, byte blue) { + cI((2UL << 24) | ((red & 255L) << 16) | ((green & 255L) << 8) | ((blue & 255L) << 0)); +} +void GDClass::ClearColorRGB(uint32_t rgb) { + cI((2UL << 24) | (rgb & 0xffffffL)); +} +void GDClass::Clear(byte c, byte s, byte t) { + byte m = (c << 2) | (s << 1) | t; + cI((38UL << 24) | m); +} +void GDClass::Clear(void) { + cI((38UL << 24) | 7); +} +void GDClass::ClearStencil(byte s) { + cI((17UL << 24) | ((s & 255L) << 0)); +} +void GDClass::ClearTag(byte s) { + cI((18UL << 24) | ((s & 255L) << 0)); +} +void GDClass::ColorA(byte alpha) { + cI((16UL << 24) | ((alpha & 255L) << 0)); +} +void GDClass::ColorMask(byte r, byte g, byte b, byte a) { + cI((32UL << 24) | ((r & 1L) << 3) | ((g & 1L) << 2) | ((b & 1L) << 1) | ((a & 1L) << 0)); +} +void GDClass::ColorRGB(byte red, byte green, byte blue) { + // cI((4UL << 24) | ((red & 255L) << 16) | ((green & 255L) << 8) | ((blue & 255L) << 0)); + union { + uint32_t c; + uint8_t b[4]; + }; + b[0] = blue; + b[1] = green; + b[2] = red; + b[3] = 4; + cI(c); +} +void GDClass::ColorRGB(uint32_t rgb) { + cI((4UL << 24) | (rgb & 0xffffffL)); +} +void GDClass::Display(void) { + cI((0UL << 24)); +} +void GDClass::End(void) { + cI((33UL << 24)); +} +void GDClass::Jump(uint16_t dest) { + cI((30UL << 24) | ((dest & 2047L) << 0)); +} +void GDClass::LineWidth(uint16_t width) { + cI((14UL << 24) | ((width & 4095L) << 0)); +} +void GDClass::Macro(byte m) { + cI((37UL << 24) | ((m & 1L) << 0)); +} +void GDClass::PointSize(uint16_t size) { + cI((13UL << 24) | ((size & 8191L) << 0)); +} +void GDClass::RestoreContext(void) { + cI((35UL << 24)); +} +void GDClass::Return(void) { + cI((36UL << 24)); +} +void GDClass::SaveContext(void) { + cI((34UL << 24)); +} +void GDClass::ScissorSize(uint16_t width, uint16_t height) { + cI((28UL << 24) | ((width & 1023L) << 10) | ((height & 1023L) << 0)); +} +void GDClass::ScissorXY(uint16_t x, uint16_t y) { + cI((27UL << 24) | ((x & 511L) << 9) | ((y & 511L) << 0)); +} +void GDClass::StencilFunc(byte func, byte ref, byte mask) { + cI((10UL << 24) | ((func & 7L) << 16) | ((ref & 255L) << 8) | ((mask & 255L) << 0)); +} +void GDClass::StencilMask(byte mask) { + cI((19UL << 24) | ((mask & 255L) << 0)); +} +void GDClass::StencilOp(byte sfail, byte spass) { + cI((12UL << 24) | ((sfail & 7L) << 3) | ((spass & 7L) << 0)); +} +void GDClass::TagMask(byte mask) { + cI((20UL << 24) | ((mask & 1L) << 0)); +} +void GDClass::Tag(byte s) { + cI((3UL << 24) | ((s & 255L) << 0)); +} +void GDClass::Vertex2f(int16_t x, int16_t y) { + // x = int(16 * x); + // y = int(16 * y); + cI((1UL << 30) | ((x & 32767L) << 15) | ((y & 32767L) << 0)); +} +void GDClass::Vertex2ii(uint16_t x, uint16_t y, byte handle, byte cell) { + // cI((2UL << 30) | ((x & 511L) << 21) | ((y & 511L) << 12) | ((handle & 31L) << 7) | ((cell & 127L) << 0)); + union { + uint32_t c; + uint8_t b[4]; + }; + b[0] = cell | ((handle & 1) << 7); + b[1] = (handle >> 1) | (y << 4); + b[2] = (y >> 4) | (x << 5); + b[3] = (2 << 6) | (x >> 3); + cI(c); +} + +void GDClass::fmtcmd(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + byte sz = 0; // Only the low 2 bits matter + const char *s; + + while (*fmt) + switch (*fmt++) { + case 'i': + case 'I': + cI(va_arg(ap, uint32_t)); + break; + case 'h': + case 'H': + cH(va_arg(ap, unsigned int)); + sz += 2; + break; + case 's': + s = va_arg(ap, const char*); + cs(s); + sz += strlen(s) + 1; + break; + } + align(sz); +} + +void GDClass::cmd_append(uint32_t ptr, uint32_t num) { + cFFFFFF(0x1e); + cI(ptr); + cI(num); +} +void GDClass::cmd_bgcolor(uint32_t c) { + fmtcmd("II", 0xffffff09UL, c); +} +void GDClass::cmd_button(int16_t x, int16_t y, uint16_t w, uint16_t h, byte font, uint16_t options, const char *s) { + fmtcmd("IhhhhhHs", 0xffffff0dUL, x, y, w, h, font, options, s); +} +void GDClass::cmd_calibrate(void) { + cFFFFFF(0x15); + cFFFFFF(0xff); +} +void GDClass::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) { + fmtcmd("IhhhHHHHH", 0xffffff14UL, x, y, r, options, h, m, s, ms); +} +void GDClass::cmd_coldstart(void) { + cFFFFFF(0x32); +} +void GDClass::cmd_dial(int16_t x, int16_t y, int16_t r, uint16_t options, uint16_t val) { + fmtcmd("IhhhHH", 0xffffff2dUL, x, y, r, options, val); +} +void GDClass::cmd_dlstart(void) { + cFFFFFF(0x00); +} +void GDClass::cmd_fgcolor(uint32_t c) { + fmtcmd("II", 0xffffff0aUL, c); +} +void GDClass::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) { + fmtcmd("IhhhHHHHH", 0xffffff13UL, x, y, r, options, major, minor, val, range); +} +void GDClass::cmd_getmatrix(void) { + fmtcmd("Iiiiiii", 0xffffff33UL, 0, 0, 0, 0, 0, 0); +} +void GDClass::cmd_getprops(uint32_t &ptr, uint32_t &w, uint32_t &h) { + cFFFFFF(0x25); + ptr = GDTR.getwp(); + cI(0); + w = GDTR.getwp(); + cI(0); + h = GDTR.getwp(); + cI(0); +} +void GDClass::cmd_getptr(void) { + fmtcmd("II", 0xffffff23UL, 0); +} +void GDClass::cmd_gradcolor(uint32_t c) { + fmtcmd("II", 0xffffff34UL, c); +} +void GDClass::cmd_gradient(int16_t x0, int16_t y0, uint32_t rgb0, int16_t x1, int16_t y1, uint32_t rgb1) { + fmtcmd("IhhIhhI", 0xffffff0bUL, x0, y0, rgb0, x1, y1, rgb1); +} +void GDClass::cmd_inflate(uint32_t ptr) { + cFFFFFF(0x22); + cI(ptr); +} +void GDClass::cmd_interrupt(uint32_t ms) { + fmtcmd("II", 0xffffff02UL, ms); +} +void GDClass::cmd_keys(int16_t x, int16_t y, int16_t w, int16_t h, byte font, uint16_t options, const char*s) { + fmtcmd("IhhhhhHs", 0xffffff0eUL, x, y, w, h, font, options, s); +} +void GDClass::cmd_loadidentity(void) { + cFFFFFF(0x26); +} +void GDClass::cmd_loadimage(uint32_t ptr, int32_t options) { + fmtcmd("III", 0xffffff24UL, ptr, options); +} +void GDClass::cmd_memcpy(uint32_t dest, uint32_t src, uint32_t num) { + fmtcmd("IIII", 0xffffff1dUL, dest, src, num); +} +void GDClass::cmd_memset(uint32_t ptr, byte value, uint32_t num) { + cFFFFFF(0x1b); + cI(ptr); + cI((uint32_t)value); + cI(num); +} +uint32_t GDClass::cmd_memcrc(uint32_t ptr, uint32_t num) { + cFFFFFF(0x18); + cI(ptr); + cI(num); + uint32_t r = GDTR.getwp(); + cI(0xFFFFFFFF); + return r; +} +void GDClass::cmd_memwrite(uint32_t ptr, uint32_t num) { + fmtcmd("III", 0xffffff1aUL, ptr, num); +} +void GDClass::cmd_regwrite(uint32_t ptr, uint32_t val) { + cFFFFFF(0x1a); + cI(ptr); + cI(4UL); + cI(val); +} +void GDClass::cmd_number(int16_t x, int16_t y, byte font, uint16_t options, uint32_t n) { + // fmtcmd("IhhhHi", 0xffffff2eUL, x, y, font, options, n); + cFFFFFF(0x2e); + ch(x); + ch(y); + ch(font); + cH(options); + ci(n); +} +void GDClass::cmd_progress(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t options, uint16_t val, uint16_t range) { + fmtcmd("IhhhhHHH", 0xffffff0fUL, x, y, w, h, options, val, range); +} +void GDClass::cmd_regread(uint32_t ptr) { + fmtcmd("III", 0xffffff19UL, ptr, 0); +} +void GDClass::cmd_rotate(int32_t a) { + cFFFFFF(0x29); + ci(a); +} +void GDClass::cmd_scale(int32_t sx, int32_t sy) { + cFFFFFF(0x28); + ci(sx); + ci(sy); +} +void GDClass::cmd_screensaver(void) { + cFFFFFF(0x2f); +} +void GDClass::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) { + fmtcmd("IhhhhHHHH", 0xffffff11UL, x, y, w, h, options, val, size, range); +} +void GDClass::cmd_setfont(byte font, uint32_t ptr) { + fmtcmd("III", 0xffffff2bUL, font, ptr); +} +void GDClass::cmd_setmatrix(void) { + cFFFFFF(0x2a); +} +void GDClass::cmd_sketch(int16_t x, int16_t y, uint16_t w, uint16_t h, uint32_t ptr, uint16_t format) { + cFFFFFF(0x30); + ch(x); + ch(y); + cH(w); + cH(h); + cI(ptr); + cI(format); +} +void GDClass::cmd_slider(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t options, uint16_t val, uint16_t range) { + fmtcmd("IhhhhHHH", 0xffffff10UL, x, y, w, h, options, val, range); +} +void GDClass::cmd_snapshot(uint32_t ptr) { + fmtcmd("II", 0xffffff1fUL, ptr); +} +void GDClass::cmd_spinner(int16_t x, int16_t y, byte style, byte scale) { + cFFFFFF(0x16); + ch(x); + ch(y); + cH(style); + cH(scale); +} +void GDClass::cmd_stop(void) { + cFFFFFF(0x17); +} +void GDClass::cmd_swap(void) { + cFFFFFF(0x01); +} +void GDClass::cmd_text(int16_t x, int16_t y, byte font, uint16_t options, const char *s) { + // fmtcmd("IhhhHs", 0xffffff0cUL, x, y, font, options, s); + cFFFFFF(0x0c); + ch(x); + ch(y); + ch(font); + cH(options); + cs(s); + align(strlen(s) + 1); +} +void GDClass::cmd_toggle(int16_t x, int16_t y, int16_t w, byte font, uint16_t options, uint16_t state, const char *s) { + fmtcmd("IhhhhHHs", 0xffffff12UL, x, y, w, font, options, state, s); +} +void GDClass::cmd_track(int16_t x, int16_t y, uint16_t w, uint16_t h, byte tag) { + fmtcmd("Ihhhhh", 0xffffff2cUL, x, y, w, h, tag); +} +void GDClass::cmd_translate(int32_t tx, int32_t ty) { + cFFFFFF(0x27); + ci(tx); + ci(ty); +} + +byte GDClass::rd(uint32_t addr) +{ + return GDTR.rd(addr); +} +void GDClass::wr(uint32_t addr, uint8_t v) +{ + GDTR.wr(addr, v); +} +uint16_t GDClass::rd16(uint32_t addr) +{ + return GDTR.rd16(addr); +} +void GDClass::wr16(uint32_t addr, uint16_t v) +{ + GDTR.wr16(addr, v); +} +uint32_t GDClass::rd32(uint32_t addr) +{ + return GDTR.rd32(addr); +} +void GDClass::wr32(uint32_t addr, uint32_t v) +{ + GDTR.wr32(addr, v); +} +void GDClass::wr_n(uint32_t addr, byte *src, uint32_t n) +{ + GDTR.wr_n(addr, src, n); +} + +void GDClass::cmdbyte(uint8_t b) +{ + GDTR.cmdbyte(b); +} +void GDClass::cmd32(uint32_t b) { + GDTR.cmd32(b); +} +void GDClass::finish(void) { + GDTR.finish(); +} +void GDClass::get_accel(int &x, int &y, int &z) +{ + static float f[3]; + + for (byte i = 0; i < 3; i++) + { + float a = accel[i]->read() * 1000; + // Serial.print(a, DEC); Serial.print(" "); + int s = (-160 * ((int)(a - 376)) >> 6); + f[i] = (((int)(3 * f[i])) >> 2) + (s >> 2); + } + // DEBUGOUT(); + x = f[2]; + y = f[1]; + z = f[0]; +} +void GDClass::get_inputs(void) { + GDTR.finish(); + byte *bi = (byte*)&inputs; + GDTR.rd_n(bi, REG_TRACKER, 4); + GDTR.rd_n(bi + 4, REG_TOUCH_RZ, 13); + GDTR.rd_n(bi + 17, REG_TAG, 1); +#if DUMP_INPUTS + for (size_t i = 0; i < sizeof(inputs); i++) { + DEBUGOUT("%x", bi[i]); + DEBUGOUT(" "); + } +#endif +} +void GDClass::bulkrd(uint32_t a) { + GDTR.bulk(a); +} +void GDClass::resume(void) { + GDTR.resume(); +} +void GDClass::__end(void) { + GDTR.__end(); +} +void GDClass::play(uint8_t instrument, uint8_t note) { + wr16(REG_SOUND, (note << 8) | instrument); + wr(REG_PLAY, 1); +} +void GDClass::sample(uint32_t start, uint32_t len, uint16_t freq, uint16_t format, int loop) +{ + wr32(REG_PLAYBACK_START, start); + wr32(REG_PLAYBACK_LENGTH, len); + wr16(REG_PLAYBACK_FREQ, freq); + wr(REG_PLAYBACK_FORMAT, format); + wr(REG_PLAYBACK_LOOP, loop); + wr(REG_PLAYBACK_PLAY, 1); +} +void GDClass::reset() { + GDTR.__end(); + GDTR.wr(REG_CPURESET, 1); + GDTR.wr(REG_CPURESET, 0); + GDTR.resume(); +} + + +// Load named file from storage +// returns 0 on failure (e.g. file not found), 1 on success + +byte GDClass::load(const char *filename, void (*progress)(long, long)) +{ +#if defined(RASPBERRY_PI) + FILE *f = fopen(filename, "rb"); + if (!f) { + perror(filename); + exit(1); + } + byte buf[512]; + int n; + while ((n = fread(buf, 1, 512, f)) > 0) { + GDTR.cmd_n(buf, (n + 3) & ~3); + } + fclose(f); + return 1; +#else + __end(); + Reader* r = new Reader(GDTR.SPI(), SD); + if (r->openfile(filename)) + { + byte buf[512]; + while (r->offset < r->size) + { + uint16_t n = min(512, r->size - r->offset); + n = (n + 3) & ~3; // force 32-bit alignment + r->readsector(buf); + + resume(); + if (progress) + (*progress)(r->offset, r->size); + copyram(buf, n); + GDTR.stop(); + } + resume(); + delete r; + return 1; + } + resume(); + delete r; + return 0; +#endif +} + +// Generated by mk_bsod.py. Blue screen with 'ERROR' text +static const unsigned char __bsod[31] = { + 0, 255, 255, 255, 255, 0, 0, 2, 7, 0, 0, 38, 12, 255, 255, 255, 240, + 0, 120, 0, 28, 0, 0, 6, 69, 82, 82, 79, 82, 33, 0 +}; +// "Cannot open file" text +static const unsigned char __bsod_badfile[31] = { + 12, 255, 255, 255, 240, 0, 148, 0, 28, 0, 0, 6, 67, 97, 110, 110, 111, + 116, 32, 111, 112, 101, 110, 32, 102, 105, 108, 101, 0, 0, 0 +}; + +void GDClass::safeload(const char *filename) +{ + if (!load(filename)) { + copy(__bsod, sizeof(__bsod)); + copy(__bsod_badfile, sizeof(__bsod_badfile)); + cmd_text(240, 176, 28, OPT_CENTER, filename); + swap(); + for (;;) + ; + } +} \ No newline at end of file