Library(Beta) for Gameduino 2
Revision 0:9c211972beb2, committed 2014-04-11
- Comitter:
- aluqard
- Date:
- Fri Apr 11 07:24:23 2014 +0000
- Commit message:
- Initial release for Gameduino 2
Changed in this revision
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
diff -r 000000000000 -r 9c211972beb2 GD2.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GD2.h Fri Apr 11 07:24:23 2014 +0000 @@ -0,0 +1,205 @@ +#ifndef _GAMEDUINO2_H_ +#define _GAMEDUINO2_H_ + +#include "mbed.h" +#include "arduino.h" +#include "GDTransport.h" + +#define PROTO 1 +#define STORAGE 1 +#define CALIBRATION 0 +#define DUMP_INPUTS 0 +#define VERBOSE 0 + +#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 + +#define REG_TRIM 0x10256C +#define LOW_FREQ_BOUND 47040000UL + +class sdcard; + +class GDClass +{ +public: + GDClass(PinName mosi, PinName miso, PinName sclk, PinName graphic_cs, PinName sdcard_cs); + + GDTransport GDTR; + sdcard *SD; + AnalogIn *accel[3]; + PinName _sdcard_cs; + + sdcard* getSD() { return SD; } + void begin(unsigned char options = (GD_CALIBRATE | GD_TRIM | GD_STORAGE)); + + unsigned short random(); + unsigned short random(unsigned short n); + void seed(unsigned short n); + short rsin(short r, unsigned short th); + short rcos(short r, unsigned short th); + void polar(int &x, int &y, short r, unsigned short th); + unsigned short atan2(short y, short x); + + void copy(const unsigned char *src, int count); + void copyram(unsigned char *src, int count); + + void self_calibrate(void); + + void swap(void); + void flush(void); + void finish(void); + + void play(unsigned char instrument, unsigned char note = 0); + void sample(unsigned int start, unsigned int len, unsigned short freq, unsigned short format, int loop = 0); + + void get_inputs(void); + void get_accel(int &x, int &y, int &z); + struct { + unsigned short track_tag; + unsigned short track_val; + unsigned short rz; + unsigned short __dummy_1; + short y; + short x; + short tag_y; + short tag_x; + unsigned char tag; + unsigned char ptag; + } inputs; + + void AlphaFunc(unsigned char func, unsigned char ref); + void Begin(unsigned char prim); + void BitmapHandle(unsigned char handle); + void BitmapLayout(unsigned char format, unsigned short linestride, unsigned short height); + void BitmapSize(unsigned char filter, unsigned char wrapx, unsigned char wrapy, unsigned short width, unsigned short height); + void BitmapSource(unsigned int addr); + void BitmapTransformA(int a); + void BitmapTransformB(int b); + void BitmapTransformC(int c); + void BitmapTransformD(int d); + void BitmapTransformE(int e); + void BitmapTransformF(int f); + void BlendFunc(unsigned char src, unsigned char dst); + void Call(unsigned short dest); + void Cell(unsigned char cell); + void ClearColorA(unsigned char alpha); + void ClearColorRGB(unsigned char red, unsigned char green, unsigned char blue); + void ClearColorRGB(unsigned int rgb); + void Clear(unsigned char c, unsigned char s, unsigned char t); + void Clear(void); + void ClearStencil(unsigned char s); + void ClearTag(unsigned char s); + void ColorA(unsigned char alpha); + void ColorMask(unsigned char r, unsigned char g, unsigned char b, unsigned char a); + void ColorRGB(unsigned char red, unsigned char green, unsigned char blue); + void ColorRGB(unsigned int rgb); + void Display(void); + void End(void); + void Jump(unsigned short dest); + void LineWidth(unsigned short width); + void Macro(unsigned char m); + void PointSize(unsigned short size); + void RestoreContext(void); + void Return(void); + void SaveContext(void); + void ScissorSize(unsigned short width, unsigned short height); + void ScissorXY(unsigned short x, unsigned short y); + void StencilFunc(unsigned char func, unsigned char ref, unsigned char mask); + void StencilMask(unsigned char mask); + void StencilOp(unsigned char sfail, unsigned char spass); + void TagMask(unsigned char mask); + void Tag(unsigned char s); + void Vertex2f(short x, short y); + void Vertex2ii(unsigned short x, unsigned short y, unsigned char handle = 0, unsigned char cell = 0); + + // Higher-level graphics commands + + void cmd_append(unsigned int ptr, unsigned int num); + void cmd_bgcolor(unsigned int c); + void cmd_button(short x, short y, unsigned short w, unsigned short h, unsigned char font, unsigned short options, const char *s); + void cmd_calibrate(void); + void cmd_clock(short x, short y, short r, unsigned short options, unsigned short h, unsigned short m, unsigned short s, unsigned short ms); + void cmd_coldstart(void); + void cmd_dial(short x, short y, short r, unsigned short options, unsigned short val); + void cmd_dlstart(void); + void cmd_fgcolor(unsigned int c); + void cmd_gauge(short x, short y, short r, unsigned short options, unsigned short major, unsigned short minor, unsigned short val, unsigned short range); + void cmd_getmatrix(void); + void cmd_getprops(unsigned int &ptr, unsigned int &w, unsigned int &h); + void cmd_getptr(void); + void cmd_gradcolor(unsigned int c); + void cmd_gradient(short x0, short y0, unsigned int rgb0, short x1, short y1, unsigned int rgb1); + void cmd_inflate(unsigned int ptr); + void cmd_interrupt(unsigned int ms); + void cmd_keys(short x, short y, short w, short h, unsigned char font, unsigned short options, const char*s); + void cmd_loadidentity(void); + void cmd_loadimage(unsigned int ptr, int options); + void cmd_memcpy(unsigned int dest, unsigned int src, unsigned int num); + void cmd_memset(unsigned int ptr, unsigned char value, unsigned int num); + unsigned int cmd_memcrc(unsigned int ptr, unsigned int num); + void cmd_memwrite(unsigned int ptr, unsigned int num); + void cmd_regwrite(unsigned int ptr, unsigned int val); + void cmd_number(short x, short y, unsigned char font, unsigned short options, unsigned int n); + void cmd_progress(short x, short y, short w, short h, unsigned short options, unsigned short val, unsigned short range); + void cmd_regread(unsigned int ptr); + void cmd_rotate(int a); + void cmd_scale(int sx, int sy); + void cmd_screensaver(void); + void cmd_scrollbar(short x, short y, short w, short h, unsigned short options, unsigned short val, unsigned short size, unsigned short range); + void cmd_setfont(unsigned char font, unsigned int ptr); + void cmd_setmatrix(void); + void cmd_sketch(short x, short y, unsigned short w, unsigned short h, unsigned int ptr, unsigned short format); + void cmd_slider(short x, short y, unsigned short w, unsigned short h, unsigned short options, unsigned short val, unsigned short range); + void cmd_snapshot(unsigned int ptr); + void cmd_spinner(short x, short y, unsigned char style, unsigned char scale); + void cmd_stop(void); + void cmd_swap(void); + void cmd_text(short x, short y, unsigned char font, unsigned short options, const char *s); + void cmd_toggle(short x, short y, short w, unsigned char font, unsigned short options, unsigned short state, const char *s); + void cmd_track(short x, short y, unsigned short w, unsigned short h, unsigned char tag); + void cmd_translate(int tx, int ty); + + unsigned char rd(unsigned int addr); + void wr(unsigned int addr, unsigned char v); + unsigned short rd16(unsigned int addr); + void wr16(unsigned int addr, unsigned short v); + unsigned int rd32(unsigned int addr); + void wr32(unsigned int addr, unsigned int v); + void wr_n(unsigned int addr, unsigned char *src, unsigned int n); + + void cmd32(unsigned int b); + + void bulkrd(unsigned int a); + void resume(void); + void __end(void); + void reset(void); + + void dumpscreen(void); + unsigned char load(const char *filename, void (*progress)(long, long) = NULL); + void safeload(const char *filename); + + void storage(void); + void tune(void); + +private: + void cFFFFFF(unsigned char v); + void cI(unsigned int); + void ci(int); + void cH(unsigned short); + void ch(short); + void cs(const char *); + void fmtcmd(const char *fmt, ...); + + void align(unsigned char n); + void cmdbyte(unsigned char b); + + unsigned int measure_freq(void); + + unsigned short lfsr, lcg; +}; +#endif
diff -r 000000000000 -r 9c211972beb2 GDTransport.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/GDTransport.h Fri Apr 11 07:24:23 2014 +0000 @@ -0,0 +1,524 @@ +#ifndef _GDTRANSPORT_H_ +#define _GDTRANSPORT_H_ + +#include "mbed.h" +#include "arduino.h" + +#ifndef DEBUGOUT +//#define DEBUGOUT (x,...) std::printf(x, ##y); +#define DEBUGOUT(x, ...) std::printf(""x"\r\n", ##__VA_ARGS__); +#endif + +// Convert degrees to Furmans +#define DEGREES(n) ((65536UL * (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 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 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_CMD 1081344UL +#define RAM_DL 1048576UL +#define RAM_PAL 1056768UL + +#define REG_CLOCK 1057800UL +#define REG_CMD_DL 1058028UL +#define REG_CMD_READ 1058020UL +#define REG_CMD_WRITE 1058024UL +#define REG_CPURESET 1057820UL +#define REG_CSPREAD 1057892UL +#define REG_DITHER 1057884UL +#define REG_DLSWAP 1057872UL +#define REG_FRAMES 1057796UL +#define REG_FREQUENCY 1057804UL +#define REG_GPIO 1057936UL +#define REG_GPIO_DIR 1057932UL +#define REG_HCYCLE 1057832UL +#define REG_HOFFSET 1057836UL +#define REG_HSIZE 1057840UL +#define REG_HSYNC0 1057844UL +#define REG_HSYNC1 1057848UL +#define REG_ID 1057792UL +#define REG_INT_EN 1057948UL +#define REG_INT_FLAGS 1057944UL +#define REG_INT_MASK 1057952UL +#define REG_MACRO_0 1057992UL +#define REG_MACRO_1 1057996UL +#define REG_OUTBITS 1057880UL +#define REG_PCLK 1057900UL +#define REG_PCLK_POL 1057896UL +#define REG_PLAY 1057928UL +#define REG_PLAYBACK_FORMAT 1057972UL +#define REG_PLAYBACK_FREQ 1057968UL +#define REG_PLAYBACK_LENGTH 1057960UL +#define REG_PLAYBACK_LOOP 1057976UL +#define REG_PLAYBACK_PLAY 1057980UL +#define REG_PLAYBACK_READPTR 1057964UL +#define REG_PLAYBACK_START 1057956UL +#define REG_PWM_DUTY 1057988UL +#define REG_PWM_HZ 1057984UL +#define REG_ROTATE 1057876UL +#define REG_SOUND 1057924UL +#define REG_SWIZZLE 1057888UL +#define REG_TAG 1057912UL +#define REG_TAG_X 1057904UL +#define REG_TAG_Y 1057908UL +#define REG_TOUCH_ADC_MODE 1058036UL +#define REG_TOUCH_CHARGE 1058040UL +#define REG_TOUCH_DIRECT_XY 1058164UL +#define REG_TOUCH_DIRECT_Z1Z2 1058168UL +#define REG_TOUCH_MODE 1058032UL +#define REG_TOUCH_OVERSAMPLE 1058048UL +#define REG_TOUCH_RAW_XY 1058056UL +#define REG_TOUCH_RZ 1058060UL +#define REG_TOUCH_RZTHRESH 1058052UL +#define REG_TOUCH_SCREEN_XY 1058064UL +#define REG_TOUCH_SETTLE 1058044UL +#define REG_TOUCH_TAG 1058072UL +#define REG_TOUCH_TAG_XY 1058068UL +#define REG_TOUCH_TRANSFORM_A 1058076UL +#define REG_TOUCH_TRANSFORM_B 1058080UL +#define REG_TOUCH_TRANSFORM_C 1058084UL +#define REG_TOUCH_TRANSFORM_D 1058088UL +#define REG_TOUCH_TRANSFORM_E 1058092UL +#define REG_TOUCH_TRANSFORM_F 1058096UL +#define REG_TRACKER 1085440UL +#define REG_VCYCLE 1057852UL +#define REG_VOFFSET 1057856UL +#define REG_VOL_PB 1057916UL +#define REG_VOL_SOUND 1057920UL +#define REG_VSIZE 1057860UL +#define REG_VSYNC0 1057864UL +#define REG_VSYNC1 1057868UL + +#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 GDTransport { +protected: + SPI _spi; + DigitalOut _cs; + + byte streaming; + uint16_t wp; + uint16_t freespace; + +public: + GDTransport(PinName mosi, PinName miso, PinName sclk, PinName cs) + : _spi(mosi, miso, sclk) + , _cs(cs) + { + } + + void begin() + { + _spi.format(8, 0); + _spi.frequency(10000000); + + _cs = 1; + + hostcmd(0x00); // FT_GPU_ACTIVE_M + + hostcmd(0x62); // Switch PLL output to 48MHz + + hostcmd(0x68); // FT_GPU_CORE_RESET + + _spi.frequency(16000000); + + byte chipid = rd(REG_ID); + + DEBUGOUT("0x%x", chipid); + + wp = 0; + freespace = 4096 - 4; + + stream(); + } + + SPI* SPI() + { + return &_spi; + } + + void cmd32(uint32_t x) + { + if (freespace < 4) + { + getfree(4); + } + wp += 4; + freespace -= 4; + union + { + uint32_t c; + uint8_t b[4]; + }; + c = x; + _spi.write(b[0]); + _spi.write(b[1]); + _spi.write(b[2]); + _spi.write(b[3]); + } + void cmdbyte(byte x) + { + if (freespace == 0) + { + getfree(1); + } + wp++; + freespace--; + _spi.write(x); + } + void cmd_n(byte *s, uint16_t n) + { + if (freespace < n) + { + getfree(n); + } + wp += n; + freespace -= n; + while (n > 8) + { + n -= 8; + _spi.write(*s++); + _spi.write(*s++); + _spi.write(*s++); + _spi.write(*s++); + _spi.write(*s++); + _spi.write(*s++); + _spi.write(*s++); + _spi.write(*s++); + } + while (n--) + _spi.write(*s++); + } + + void flush() + { + getfree(0); + } + uint16_t rp() + { + uint16_t r = __rd16(REG_CMD_READ); + + if (r == 0xfff) + { + for (;;) ; + } + return r; + } + void finish() + { + wp &= 0xffc; + __end(); + __wr16(REG_CMD_WRITE, wp); + + while (rp() != wp); + + stream(); + } + + byte rd(uint32_t addr) + { + __end(); // stop streaming + __start(addr); + byte r = _spi.write(0); + stream(); + + return r; + } + + void wr(uint32_t addr, byte v) + { + __end(); // stop streaming + __wstart(addr); + _spi.write(v); + stream(); + } + + uint16_t rd16(uint32_t addr) + { + uint16_t r = 0; + __end(); // stop streaming + __start(addr); + r = _spi.write(0); + r |= (_spi.write(0) << 8); + stream(); + return r; + } + + void wr16(uint32_t addr, uint32_t v) + { + __end(); // stop streaming + __wstart(addr); + + _spi.write(v); + _spi.write(v >> 8); + stream(); + } + + uint32_t rd32(uint32_t addr) + { + __end(); // stop streaming + __start(addr); +// _spi.write(0); + union { + uint32_t c; + uint8_t b[4]; + }; + b[0] = _spi.write(0); + b[1] = _spi.write(0); + b[2] = _spi.write(0); + b[3] = _spi.write(0); + stream(); + return c; + } + void rd_n(byte *dst, uint32_t addr, uint16_t n) + { + __end(); // stop streaming + __start(addr); +// _spi.write(0); + while (n--) + *dst++ = _spi.write(0); + stream(); + } + void wr_n(uint32_t addr, byte *src, uint16_t n) + { + __end(); // stop streaming + __wstart(addr); + while (n--) + _spi.write(*src++); + stream(); + } + + void wr32(uint32_t addr, unsigned long v) + { + __end(); // stop streaming + __wstart(addr); + _spi.write(v); + _spi.write(v >> 8); + _spi.write(v >> 16); + _spi.write(v >> 24); + stream(); + } + + uint32_t getwp(void) + { + return RAM_CMD + (wp & 0xffc); + } + + void bulk(uint32_t addr) + { + __end(); // stop streaming + __start(addr); + } + void resume(void) + { + stream(); + } + + void __start(uint32_t addr) // start an SPI transaction to addr + { + _cs = 0; + _spi.write(addr >> 16); + _spi.write(addr >> 8); + _spi.write(addr & 0xff ); + _spi.write(0); + } + + void __wstart(uint32_t addr) // start an SPI write transaction to addr + { + _cs = 0; + _spi.write(0x80 | (addr >> 16)); + _spi.write(addr >> 8); + _spi.write(addr & 0xff); + } + + void __end() // end the SPI transaction + { + _cs = 1; + } + + void stop() // end the SPI transaction + { + wp &= 0xffc; + __end(); + __wr16(REG_CMD_WRITE, wp); + } + + void stream(void) { + __end(); + __wstart(RAM_CMD + (wp & 0xfff)); + } + + uint32_t __rd16(uint32_t addr) + { + uint32_t r; + + __start(addr); + r = _spi.write(0); + r |= (_spi.write(0) << 8); + __end(); + return r; + } + + void __wr16(uint32_t addr, uint32_t v) + { + __wstart(addr); + _spi.write(lowByte(v)); + _spi.write(highByte(v)); + __end(); + } + + void hostcmd(byte a) + { + _cs = 0; + + _spi.write(a); + _spi.write(0x00); + _spi.write(0x00); + + _cs = 1; + + delay(60); + } + + void getfree(uint16_t n) + { + wp &= 0xfff; + __end(); + __wr16(REG_CMD_WRITE, wp & 0xffc); + do { + uint16_t fullness = (wp - rp()) & 4095; + freespace = (4096 - 4) - fullness; + } while (freespace < n); + stream(); + } +}; + +#endif \ No newline at end of file
diff -r 000000000000 -r 9c211972beb2 Utils.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Utils.h Fri Apr 11 07:24:23 2014 +0000 @@ -0,0 +1,600 @@ +#ifndef _UTILS_H_ +#define _UTILS_H_ + +#include "arduino.h" + +void loop(); + +#define LOOP while(1) loop() + +typedef struct { + byte handle; + uint16_t w, h; + uint16_t size; +} shape_t; + +struct direntry +{ + char name[8]; + char ext[3]; + uint8_t attribute; + uint8_t 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 + +class sdcard +{ +public: + SPI* _spi; + DigitalOut _cs; + uint8_t ccs; + + uint8_t 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; +public: + sdcard(SPI* spi, PinName cs) : _cs(cs) + { + _spi = spi; + } + + void sel() + { + _cs = 0; + delay(1); + } + void desel() + { + _cs = 1; + _spi->write(0xff); // force DO release + } + void sd_delay(uint8_t n) + { + while (n--) + _spi->write(0xff); + } + + void cmd(uint8_t cmd, uint32_t lba = 0, uint8_t crc = 0x95) + { + sel(); + _spi->write(0xff); + _spi->write(0x40 | cmd); + _spi->write(0xff & (lba >> 24)); + _spi->write(0xff & (lba >> 16)); + _spi->write(0xff & (lba >> 8)); + _spi->write(0xff & (lba)); + _spi->write(crc); + _spi->write(0xff); + } + + uint8_t R1() + { // read response R1 + uint8_t r; + while ((r = _spi->write(0xff)) & 0x80) + ; + desel(); + _spi->write(0xff); // trailing uint8_t + return r; + } + + uint8_t sdR3(uint32_t &ocr) + { // read response R3 + uint32_t r; + while ((r = _spi->write(0xff)) & 0x80) + ; + for (uint8_t i = 4; i; i--) + ocr = (ocr << 8) | _spi->write(0xff); + _spi->write(0xff); // trailing uint8_t + + desel(); + return r; + } + + uint8_t sdR7() + { // read response R3 + uint32_t r; + while ((r = _spi->write(0xff)) & 0x80) + ; + for (uint8_t i = 4; i; i--) + // Serial.println(____spi->write(0xff), HEX); + _spi->write(0xff); + desel(); + + return r; + } + + void appcmd(uint8_t cc, uint32_t lba = 0) + { + cmd(55); R1(); + cmd(cc, lba); + } + + void begin() + { + uint8_t type_code; + uint8_t sdhc; + + desel(); + + delay(10); // wait for boot + sd_delay(10); // deselected, 80 pulses + + // Tty.printf("Attempting card reset... "); + // attempt reset + uint8_t r1; + int attempts = 0; + do + { // reset, enter idle + cmd(0); + while ((r1 = _spi->write(0xff)) & 0x80) + if (++attempts == 1000) + return; + desel(); + _spi->write(0xff); // trailing uint8_t + } while (r1 != 1); + // Tty.printf("reset ok\n"); + + sdhc = 0; + cmd(8, 0x1aa, 0x87); + r1 = sdR7(); + sdhc = (r1 == 1); + + // Tty.printf("card %s SDHC\n", sdhc ? "is" : "is not"); + + // Tty.printf("Sending card init command... "); + while (1) + { + appcmd(41, sdhc ? (1UL << 30) : 0); // card init + r1 = R1(); + if ((r1 & 1) == 0) + break; + delay(100); + } + // Tty.printf("OK\n"); + + if (sdhc) + { + cmd(58); + uint32_t OCR = 0; + sdR3(OCR); + ccs = 1UL & (OCR >> 30); + // Tty.printf("OCR register is %#010lx\n", long(OCR)); + } + + else + { + ccs = 0; + } + // Tty.printf("ccs = %d\n", ccs); + // REPORT(ccs); + + type_code = rd(0x1be + 0x4); + + switch (type_code) + { + default: + type = FAT16; + break; + case 0x0b: + case 0x0c: + type = FAT32; + break; + } + // REPORT(type_code); + // Tty.printf("Type code %#02x means FAT%d\n", type_code, (type == FAT16) ? 16 : 32); +#if VERBOSE + DEBUGOUT("Type "); + DEBUGOUT("%x", type_code); + DEBUGOUT(" so FAT"); + DEBUGOUT("%d\r\n", (type == FAT16) ? 16 : 32); +#endif + + 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); + + // Tty.printf("Bytes per sector: %d\n", rd2(o_partition + 0xb)); + // Tty.printf("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)); + } + } + + static char toupper(char sv) + { + char c = sv; + if( sv >= 'a' && sv <= 'z') + c = sv - ('a' - 'A'); + + return c; + } + + void cmd17(uint32_t off) + { + if (ccs) + cmd(17, off >> 9); + else + cmd(17, off & ~511L); + R1(); + sel(); + while (_spi->write(0xff) != 0xfe) + ; + } + + void rdn(uint8_t *d, uint32_t off, uint16_t n) + { + cmd17(off); + uint16_t i; + uint16_t bo = (off & 511); + for (i = 0; i < bo; i++) + _spi->write(0xff); + for (i = 0; i < n; i++) + *d++ = _spi->write(0xff); + for (i = 0; i < (514 - bo - n); i++) + _spi->write(0xff); + desel(); + } + + uint32_t rd4(uint32_t off) + { + uint32_t r; + rdn((uint8_t*)&r, off, sizeof(r)); + return r; + } + + uint16_t rd2(uint32_t off) + { + uint16_t r; + rdn((uint8_t*)&r, off, sizeof(r)); + return r; + } + + uint8_t rd(uint32_t off) + { + uint8_t r; + rdn((uint8_t*)&r, off, sizeof(r)); + return r; + } +}; + +static void dos83(uint8_t dst[11], const char *ps) +{ + uint8_t i = 0; + while (*ps) + { + if (*ps != '.') + dst[i++] = sdcard::toupper(*ps); + else + { + while (i < 8) + dst[i++] = ' '; + } + ps++; + } + while (i < 11) + dst[i++] = ' '; +} + +class Reader +{ + SPI* _spi; + sdcard* _sd; +public: + Reader(SPI* spi, sdcard* sd) + { + _spi = spi; + _sd = sd; + } + +public: + int openfile(const char *filename) + { + int i = 0; + uint8_t dosname[11] = {0, }; + direntry de = {0, }; + + dos83(dosname, filename); + + do { + _sd->rdn((uint8_t*)&de, _sd->o_root + i * 32, sizeof(de)); + if (0 == memcmp(de.name, dosname, 11)) + { + DEBUGOUT("begin(de)\r\n"); + begin(de); + return 1; + } + i++; + } while (de.name[0]); + return 0; + } + + void begin(direntry &de) + { + size = de.size; + cluster = de.cluster; + if (_sd->type == FAT32) + cluster |= ((long)de.cluster_hi << 16); + sector = 0; + offset = 0; + } + + void nextcluster() + { + if (_sd->type == FAT16) + cluster = _sd->rd2(_sd->o_fat + 2 * cluster); + else + cluster = _sd->rd4(_sd->o_fat + 4 * cluster); +#if VERBOSE + DEBUGOUT("nextcluster="); + DEBUGOUT("%d\r\n", cluster); +#endif + } + + void skipcluster() + { + nextcluster(); + offset += _sd->cluster_size; + } + void skipsector() + { + if (sector == _sd->sectors_per_cluster) { + sector = 0; + nextcluster(); + } + sector++; + offset += 512; + } + + void seek(uint32_t o) + { + while (offset < o) + { + if ((sector == _sd->sectors_per_cluster) && ((o - offset) > (long)_sd->cluster_size)) + skipcluster(); + else + skipsector(); + } + } + void readsector() + { + if (sector == _sd->sectors_per_cluster) + { + sector = 0; + nextcluster(); + } + uint32_t off = _sd->o_data + ((long)_sd->cluster_size * cluster) + (512L * sector); +#if VERBOSE + DEBUGOUT("off=0x"); + DEBUGOUT("%x", off); +#endif + _sd->cmd17(off & ~511L); + // Serial.println(2 * (micros() - t0), DEC); + sector++; + offset += 512; + } + void readsector(uint8_t *dst) + { + readsector(); + for (int i = 0; i < 64; i++) { + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + *dst++ = _spi->write(0xff); + } + _spi->write(0xff); // consume CRC + _spi->write(0xff); + _sd->desel(); + } + uint32_t cluster; + uint32_t offset; + uint32_t size; + uint8_t sector; +}; + +class Poly +{ +public: + GDClass* _gd; + Poly(GDClass* gd) + { + _gd = gd; + } + + int x0, y0, x1, y1; + int x[8], y[8]; + uint8_t n; + + void restart() + { + n = 0; + x0 = 16 * 480; + x1 = 0; + y0 = 16 * 272; + y1 = 0; + } + + void perim() + { + for (uint8_t 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(); + } +}; + +class Streamer +{ +public: + GDClass* _gd; + + Streamer(GDClass* gd, sdcard* sd) + { + r = new Reader(gd->GDTR.SPI(), sd); + _gd = gd; + } + void begin(const char *rawsamples, + uint16_t freq = 44100, + uint8_t format = ADPCM_SAMPLES, + uint32_t _base = (0x40000UL - 8192), uint16_t size = 8192) + { + r->openfile(rawsamples); + + base = _base; + mask = size - 1; + wp = 0; + + for (uint8_t 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); + // DEBUGOUT("\r\n"); + uint8_t 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; +}; + + +static uint8_t sinus(GDClass* gd, uint8_t x) +{ + return 128 + gd->rsin(128, -16384 + (x << 7)); +} + +#endif \ No newline at end of file
diff -r 000000000000 -r 9c211972beb2 arduino.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/arduino.lib Fri Apr 11 07:24:23 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/aluqard/code/arduino/#3b83fc30bbdf