Library(Beta) for Gameduino 2

Dependencies:   arduino

Dependents:   aa_gd_jw

Committer:
aluqard
Date:
Fri Apr 11 07:24:23 2014 +0000
Revision:
0:9c211972beb2
Initial release for Gameduino 2

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aluqard 0:9c211972beb2 1 #ifndef _UTILS_H_
aluqard 0:9c211972beb2 2 #define _UTILS_H_
aluqard 0:9c211972beb2 3
aluqard 0:9c211972beb2 4 #include "arduino.h"
aluqard 0:9c211972beb2 5
aluqard 0:9c211972beb2 6 void loop();
aluqard 0:9c211972beb2 7
aluqard 0:9c211972beb2 8 #define LOOP while(1) loop()
aluqard 0:9c211972beb2 9
aluqard 0:9c211972beb2 10 typedef struct {
aluqard 0:9c211972beb2 11 byte handle;
aluqard 0:9c211972beb2 12 uint16_t w, h;
aluqard 0:9c211972beb2 13 uint16_t size;
aluqard 0:9c211972beb2 14 } shape_t;
aluqard 0:9c211972beb2 15
aluqard 0:9c211972beb2 16 struct direntry
aluqard 0:9c211972beb2 17 {
aluqard 0:9c211972beb2 18 char name[8];
aluqard 0:9c211972beb2 19 char ext[3];
aluqard 0:9c211972beb2 20 uint8_t attribute;
aluqard 0:9c211972beb2 21 uint8_t reserved[8];
aluqard 0:9c211972beb2 22 uint16_t cluster_hi; // FAT32 only
aluqard 0:9c211972beb2 23 uint16_t time;
aluqard 0:9c211972beb2 24 uint16_t date;
aluqard 0:9c211972beb2 25 uint16_t cluster;
aluqard 0:9c211972beb2 26 uint32_t size;
aluqard 0:9c211972beb2 27 };
aluqard 0:9c211972beb2 28
aluqard 0:9c211972beb2 29 // https://www.sdcard.org/downloads/pls/simplified_specs/Part_1_Physical_Layer_Simplified_Specification_Ver_3.01_Final_100518.pdf
aluqard 0:9c211972beb2 30 // page 22
aluqard 0:9c211972beb2 31 // http://mac6.ma.psu.edu/space2008/RockSat/microController/sdcard_appnote_foust.pdf
aluqard 0:9c211972beb2 32 // http://elm-chan.org/docs/mmc/mmc_e.html
aluqard 0:9c211972beb2 33 // http://www.pjrc.com/tech/8051/ide/fat32.html
aluqard 0:9c211972beb2 34
aluqard 0:9c211972beb2 35 #define FAT16 0
aluqard 0:9c211972beb2 36 #define FAT32 1
aluqard 0:9c211972beb2 37
aluqard 0:9c211972beb2 38 class sdcard
aluqard 0:9c211972beb2 39 {
aluqard 0:9c211972beb2 40 public:
aluqard 0:9c211972beb2 41 SPI* _spi;
aluqard 0:9c211972beb2 42 DigitalOut _cs;
aluqard 0:9c211972beb2 43 uint8_t ccs;
aluqard 0:9c211972beb2 44
aluqard 0:9c211972beb2 45 uint8_t type;
aluqard 0:9c211972beb2 46 uint16_t sectors_per_cluster;
aluqard 0:9c211972beb2 47 uint16_t reserved_sectors;
aluqard 0:9c211972beb2 48 uint16_t max_root_dir_entries;
aluqard 0:9c211972beb2 49 uint16_t sectors_per_fat;
aluqard 0:9c211972beb2 50 uint16_t cluster_size;
aluqard 0:9c211972beb2 51 uint32_t root_dir_first_cluster;
aluqard 0:9c211972beb2 52
aluqard 0:9c211972beb2 53 // These are all linear addresses, hence the o_ prefix
aluqard 0:9c211972beb2 54 uint32_t o_partition;
aluqard 0:9c211972beb2 55 uint32_t o_fat;
aluqard 0:9c211972beb2 56 uint32_t o_root;
aluqard 0:9c211972beb2 57 uint32_t o_data;
aluqard 0:9c211972beb2 58 public:
aluqard 0:9c211972beb2 59 sdcard(SPI* spi, PinName cs) : _cs(cs)
aluqard 0:9c211972beb2 60 {
aluqard 0:9c211972beb2 61 _spi = spi;
aluqard 0:9c211972beb2 62 }
aluqard 0:9c211972beb2 63
aluqard 0:9c211972beb2 64 void sel()
aluqard 0:9c211972beb2 65 {
aluqard 0:9c211972beb2 66 _cs = 0;
aluqard 0:9c211972beb2 67 delay(1);
aluqard 0:9c211972beb2 68 }
aluqard 0:9c211972beb2 69 void desel()
aluqard 0:9c211972beb2 70 {
aluqard 0:9c211972beb2 71 _cs = 1;
aluqard 0:9c211972beb2 72 _spi->write(0xff); // force DO release
aluqard 0:9c211972beb2 73 }
aluqard 0:9c211972beb2 74 void sd_delay(uint8_t n)
aluqard 0:9c211972beb2 75 {
aluqard 0:9c211972beb2 76 while (n--)
aluqard 0:9c211972beb2 77 _spi->write(0xff);
aluqard 0:9c211972beb2 78 }
aluqard 0:9c211972beb2 79
aluqard 0:9c211972beb2 80 void cmd(uint8_t cmd, uint32_t lba = 0, uint8_t crc = 0x95)
aluqard 0:9c211972beb2 81 {
aluqard 0:9c211972beb2 82 sel();
aluqard 0:9c211972beb2 83 _spi->write(0xff);
aluqard 0:9c211972beb2 84 _spi->write(0x40 | cmd);
aluqard 0:9c211972beb2 85 _spi->write(0xff & (lba >> 24));
aluqard 0:9c211972beb2 86 _spi->write(0xff & (lba >> 16));
aluqard 0:9c211972beb2 87 _spi->write(0xff & (lba >> 8));
aluqard 0:9c211972beb2 88 _spi->write(0xff & (lba));
aluqard 0:9c211972beb2 89 _spi->write(crc);
aluqard 0:9c211972beb2 90 _spi->write(0xff);
aluqard 0:9c211972beb2 91 }
aluqard 0:9c211972beb2 92
aluqard 0:9c211972beb2 93 uint8_t R1()
aluqard 0:9c211972beb2 94 { // read response R1
aluqard 0:9c211972beb2 95 uint8_t r;
aluqard 0:9c211972beb2 96 while ((r = _spi->write(0xff)) & 0x80)
aluqard 0:9c211972beb2 97 ;
aluqard 0:9c211972beb2 98 desel();
aluqard 0:9c211972beb2 99 _spi->write(0xff); // trailing uint8_t
aluqard 0:9c211972beb2 100 return r;
aluqard 0:9c211972beb2 101 }
aluqard 0:9c211972beb2 102
aluqard 0:9c211972beb2 103 uint8_t sdR3(uint32_t &ocr)
aluqard 0:9c211972beb2 104 { // read response R3
aluqard 0:9c211972beb2 105 uint32_t r;
aluqard 0:9c211972beb2 106 while ((r = _spi->write(0xff)) & 0x80)
aluqard 0:9c211972beb2 107 ;
aluqard 0:9c211972beb2 108 for (uint8_t i = 4; i; i--)
aluqard 0:9c211972beb2 109 ocr = (ocr << 8) | _spi->write(0xff);
aluqard 0:9c211972beb2 110 _spi->write(0xff); // trailing uint8_t
aluqard 0:9c211972beb2 111
aluqard 0:9c211972beb2 112 desel();
aluqard 0:9c211972beb2 113 return r;
aluqard 0:9c211972beb2 114 }
aluqard 0:9c211972beb2 115
aluqard 0:9c211972beb2 116 uint8_t sdR7()
aluqard 0:9c211972beb2 117 { // read response R3
aluqard 0:9c211972beb2 118 uint32_t r;
aluqard 0:9c211972beb2 119 while ((r = _spi->write(0xff)) & 0x80)
aluqard 0:9c211972beb2 120 ;
aluqard 0:9c211972beb2 121 for (uint8_t i = 4; i; i--)
aluqard 0:9c211972beb2 122 // Serial.println(____spi->write(0xff), HEX);
aluqard 0:9c211972beb2 123 _spi->write(0xff);
aluqard 0:9c211972beb2 124 desel();
aluqard 0:9c211972beb2 125
aluqard 0:9c211972beb2 126 return r;
aluqard 0:9c211972beb2 127 }
aluqard 0:9c211972beb2 128
aluqard 0:9c211972beb2 129 void appcmd(uint8_t cc, uint32_t lba = 0)
aluqard 0:9c211972beb2 130 {
aluqard 0:9c211972beb2 131 cmd(55); R1();
aluqard 0:9c211972beb2 132 cmd(cc, lba);
aluqard 0:9c211972beb2 133 }
aluqard 0:9c211972beb2 134
aluqard 0:9c211972beb2 135 void begin()
aluqard 0:9c211972beb2 136 {
aluqard 0:9c211972beb2 137 uint8_t type_code;
aluqard 0:9c211972beb2 138 uint8_t sdhc;
aluqard 0:9c211972beb2 139
aluqard 0:9c211972beb2 140 desel();
aluqard 0:9c211972beb2 141
aluqard 0:9c211972beb2 142 delay(10); // wait for boot
aluqard 0:9c211972beb2 143 sd_delay(10); // deselected, 80 pulses
aluqard 0:9c211972beb2 144
aluqard 0:9c211972beb2 145 // Tty.printf("Attempting card reset... ");
aluqard 0:9c211972beb2 146 // attempt reset
aluqard 0:9c211972beb2 147 uint8_t r1;
aluqard 0:9c211972beb2 148 int attempts = 0;
aluqard 0:9c211972beb2 149 do
aluqard 0:9c211972beb2 150 { // reset, enter idle
aluqard 0:9c211972beb2 151 cmd(0);
aluqard 0:9c211972beb2 152 while ((r1 = _spi->write(0xff)) & 0x80)
aluqard 0:9c211972beb2 153 if (++attempts == 1000)
aluqard 0:9c211972beb2 154 return;
aluqard 0:9c211972beb2 155 desel();
aluqard 0:9c211972beb2 156 _spi->write(0xff); // trailing uint8_t
aluqard 0:9c211972beb2 157 } while (r1 != 1);
aluqard 0:9c211972beb2 158 // Tty.printf("reset ok\n");
aluqard 0:9c211972beb2 159
aluqard 0:9c211972beb2 160 sdhc = 0;
aluqard 0:9c211972beb2 161 cmd(8, 0x1aa, 0x87);
aluqard 0:9c211972beb2 162 r1 = sdR7();
aluqard 0:9c211972beb2 163 sdhc = (r1 == 1);
aluqard 0:9c211972beb2 164
aluqard 0:9c211972beb2 165 // Tty.printf("card %s SDHC\n", sdhc ? "is" : "is not");
aluqard 0:9c211972beb2 166
aluqard 0:9c211972beb2 167 // Tty.printf("Sending card init command... ");
aluqard 0:9c211972beb2 168 while (1)
aluqard 0:9c211972beb2 169 {
aluqard 0:9c211972beb2 170 appcmd(41, sdhc ? (1UL << 30) : 0); // card init
aluqard 0:9c211972beb2 171 r1 = R1();
aluqard 0:9c211972beb2 172 if ((r1 & 1) == 0)
aluqard 0:9c211972beb2 173 break;
aluqard 0:9c211972beb2 174 delay(100);
aluqard 0:9c211972beb2 175 }
aluqard 0:9c211972beb2 176 // Tty.printf("OK\n");
aluqard 0:9c211972beb2 177
aluqard 0:9c211972beb2 178 if (sdhc)
aluqard 0:9c211972beb2 179 {
aluqard 0:9c211972beb2 180 cmd(58);
aluqard 0:9c211972beb2 181 uint32_t OCR = 0;
aluqard 0:9c211972beb2 182 sdR3(OCR);
aluqard 0:9c211972beb2 183 ccs = 1UL & (OCR >> 30);
aluqard 0:9c211972beb2 184 // Tty.printf("OCR register is %#010lx\n", long(OCR));
aluqard 0:9c211972beb2 185 }
aluqard 0:9c211972beb2 186
aluqard 0:9c211972beb2 187 else
aluqard 0:9c211972beb2 188 {
aluqard 0:9c211972beb2 189 ccs = 0;
aluqard 0:9c211972beb2 190 }
aluqard 0:9c211972beb2 191 // Tty.printf("ccs = %d\n", ccs);
aluqard 0:9c211972beb2 192 // REPORT(ccs);
aluqard 0:9c211972beb2 193
aluqard 0:9c211972beb2 194 type_code = rd(0x1be + 0x4);
aluqard 0:9c211972beb2 195
aluqard 0:9c211972beb2 196 switch (type_code)
aluqard 0:9c211972beb2 197 {
aluqard 0:9c211972beb2 198 default:
aluqard 0:9c211972beb2 199 type = FAT16;
aluqard 0:9c211972beb2 200 break;
aluqard 0:9c211972beb2 201 case 0x0b:
aluqard 0:9c211972beb2 202 case 0x0c:
aluqard 0:9c211972beb2 203 type = FAT32;
aluqard 0:9c211972beb2 204 break;
aluqard 0:9c211972beb2 205 }
aluqard 0:9c211972beb2 206 // REPORT(type_code);
aluqard 0:9c211972beb2 207 // Tty.printf("Type code %#02x means FAT%d\n", type_code, (type == FAT16) ? 16 : 32);
aluqard 0:9c211972beb2 208 #if VERBOSE
aluqard 0:9c211972beb2 209 DEBUGOUT("Type ");
aluqard 0:9c211972beb2 210 DEBUGOUT("%x", type_code);
aluqard 0:9c211972beb2 211 DEBUGOUT(" so FAT");
aluqard 0:9c211972beb2 212 DEBUGOUT("%d\r\n", (type == FAT16) ? 16 : 32);
aluqard 0:9c211972beb2 213 #endif
aluqard 0:9c211972beb2 214
aluqard 0:9c211972beb2 215 o_partition = 512L * rd4(0x1be + 0x8);
aluqard 0:9c211972beb2 216 sectors_per_cluster = rd(o_partition + 0xd);
aluqard 0:9c211972beb2 217 reserved_sectors = rd2(o_partition + 0xe);
aluqard 0:9c211972beb2 218 cluster_size = 512L * sectors_per_cluster;
aluqard 0:9c211972beb2 219 // REPORT(sectors_per_cluster);
aluqard 0:9c211972beb2 220
aluqard 0:9c211972beb2 221 // Tty.printf("Bytes per sector: %d\n", rd2(o_partition + 0xb));
aluqard 0:9c211972beb2 222 // Tty.printf("Sectors per cluster: %d\n", sectors_per_cluster);
aluqard 0:9c211972beb2 223
aluqard 0:9c211972beb2 224 if (type == FAT16)
aluqard 0:9c211972beb2 225 {
aluqard 0:9c211972beb2 226 max_root_dir_entries = rd2(o_partition + 0x11);
aluqard 0:9c211972beb2 227 sectors_per_fat = rd2(o_partition + 0x16);
aluqard 0:9c211972beb2 228 o_fat = o_partition + 512L * reserved_sectors;
aluqard 0:9c211972beb2 229 o_root = o_fat + (2 * 512L * sectors_per_fat);
aluqard 0:9c211972beb2 230 // data area starts with cluster 2, so offset it here
aluqard 0:9c211972beb2 231 o_data = o_root + (max_root_dir_entries * 32L) - (2L * cluster_size);
aluqard 0:9c211972beb2 232 }
aluqard 0:9c211972beb2 233
aluqard 0:9c211972beb2 234 else
aluqard 0:9c211972beb2 235 {
aluqard 0:9c211972beb2 236 uint32_t sectors_per_fat = rd4(o_partition + 0x24);
aluqard 0:9c211972beb2 237 root_dir_first_cluster = rd4(o_partition + 0x2c);
aluqard 0:9c211972beb2 238 uint32_t fat_begin_lba = (o_partition >> 9) + reserved_sectors;
aluqard 0:9c211972beb2 239 uint32_t cluster_begin_lba = (o_partition >> 9) + reserved_sectors + (2 * sectors_per_fat);
aluqard 0:9c211972beb2 240
aluqard 0:9c211972beb2 241 o_fat = 512L * fat_begin_lba;
aluqard 0:9c211972beb2 242 o_root = (512L * (cluster_begin_lba + (root_dir_first_cluster - 2) * sectors_per_cluster));
aluqard 0:9c211972beb2 243 o_data = (512L * (cluster_begin_lba - 2 * sectors_per_cluster));
aluqard 0:9c211972beb2 244 }
aluqard 0:9c211972beb2 245 }
aluqard 0:9c211972beb2 246
aluqard 0:9c211972beb2 247 static char toupper(char sv)
aluqard 0:9c211972beb2 248 {
aluqard 0:9c211972beb2 249 char c = sv;
aluqard 0:9c211972beb2 250 if( sv >= 'a' && sv <= 'z')
aluqard 0:9c211972beb2 251 c = sv - ('a' - 'A');
aluqard 0:9c211972beb2 252
aluqard 0:9c211972beb2 253 return c;
aluqard 0:9c211972beb2 254 }
aluqard 0:9c211972beb2 255
aluqard 0:9c211972beb2 256 void cmd17(uint32_t off)
aluqard 0:9c211972beb2 257 {
aluqard 0:9c211972beb2 258 if (ccs)
aluqard 0:9c211972beb2 259 cmd(17, off >> 9);
aluqard 0:9c211972beb2 260 else
aluqard 0:9c211972beb2 261 cmd(17, off & ~511L);
aluqard 0:9c211972beb2 262 R1();
aluqard 0:9c211972beb2 263 sel();
aluqard 0:9c211972beb2 264 while (_spi->write(0xff) != 0xfe)
aluqard 0:9c211972beb2 265 ;
aluqard 0:9c211972beb2 266 }
aluqard 0:9c211972beb2 267
aluqard 0:9c211972beb2 268 void rdn(uint8_t *d, uint32_t off, uint16_t n)
aluqard 0:9c211972beb2 269 {
aluqard 0:9c211972beb2 270 cmd17(off);
aluqard 0:9c211972beb2 271 uint16_t i;
aluqard 0:9c211972beb2 272 uint16_t bo = (off & 511);
aluqard 0:9c211972beb2 273 for (i = 0; i < bo; i++)
aluqard 0:9c211972beb2 274 _spi->write(0xff);
aluqard 0:9c211972beb2 275 for (i = 0; i < n; i++)
aluqard 0:9c211972beb2 276 *d++ = _spi->write(0xff);
aluqard 0:9c211972beb2 277 for (i = 0; i < (514 - bo - n); i++)
aluqard 0:9c211972beb2 278 _spi->write(0xff);
aluqard 0:9c211972beb2 279 desel();
aluqard 0:9c211972beb2 280 }
aluqard 0:9c211972beb2 281
aluqard 0:9c211972beb2 282 uint32_t rd4(uint32_t off)
aluqard 0:9c211972beb2 283 {
aluqard 0:9c211972beb2 284 uint32_t r;
aluqard 0:9c211972beb2 285 rdn((uint8_t*)&r, off, sizeof(r));
aluqard 0:9c211972beb2 286 return r;
aluqard 0:9c211972beb2 287 }
aluqard 0:9c211972beb2 288
aluqard 0:9c211972beb2 289 uint16_t rd2(uint32_t off)
aluqard 0:9c211972beb2 290 {
aluqard 0:9c211972beb2 291 uint16_t r;
aluqard 0:9c211972beb2 292 rdn((uint8_t*)&r, off, sizeof(r));
aluqard 0:9c211972beb2 293 return r;
aluqard 0:9c211972beb2 294 }
aluqard 0:9c211972beb2 295
aluqard 0:9c211972beb2 296 uint8_t rd(uint32_t off)
aluqard 0:9c211972beb2 297 {
aluqard 0:9c211972beb2 298 uint8_t r;
aluqard 0:9c211972beb2 299 rdn((uint8_t*)&r, off, sizeof(r));
aluqard 0:9c211972beb2 300 return r;
aluqard 0:9c211972beb2 301 }
aluqard 0:9c211972beb2 302 };
aluqard 0:9c211972beb2 303
aluqard 0:9c211972beb2 304 static void dos83(uint8_t dst[11], const char *ps)
aluqard 0:9c211972beb2 305 {
aluqard 0:9c211972beb2 306 uint8_t i = 0;
aluqard 0:9c211972beb2 307 while (*ps)
aluqard 0:9c211972beb2 308 {
aluqard 0:9c211972beb2 309 if (*ps != '.')
aluqard 0:9c211972beb2 310 dst[i++] = sdcard::toupper(*ps);
aluqard 0:9c211972beb2 311 else
aluqard 0:9c211972beb2 312 {
aluqard 0:9c211972beb2 313 while (i < 8)
aluqard 0:9c211972beb2 314 dst[i++] = ' ';
aluqard 0:9c211972beb2 315 }
aluqard 0:9c211972beb2 316 ps++;
aluqard 0:9c211972beb2 317 }
aluqard 0:9c211972beb2 318 while (i < 11)
aluqard 0:9c211972beb2 319 dst[i++] = ' ';
aluqard 0:9c211972beb2 320 }
aluqard 0:9c211972beb2 321
aluqard 0:9c211972beb2 322 class Reader
aluqard 0:9c211972beb2 323 {
aluqard 0:9c211972beb2 324 SPI* _spi;
aluqard 0:9c211972beb2 325 sdcard* _sd;
aluqard 0:9c211972beb2 326 public:
aluqard 0:9c211972beb2 327 Reader(SPI* spi, sdcard* sd)
aluqard 0:9c211972beb2 328 {
aluqard 0:9c211972beb2 329 _spi = spi;
aluqard 0:9c211972beb2 330 _sd = sd;
aluqard 0:9c211972beb2 331 }
aluqard 0:9c211972beb2 332
aluqard 0:9c211972beb2 333 public:
aluqard 0:9c211972beb2 334 int openfile(const char *filename)
aluqard 0:9c211972beb2 335 {
aluqard 0:9c211972beb2 336 int i = 0;
aluqard 0:9c211972beb2 337 uint8_t dosname[11] = {0, };
aluqard 0:9c211972beb2 338 direntry de = {0, };
aluqard 0:9c211972beb2 339
aluqard 0:9c211972beb2 340 dos83(dosname, filename);
aluqard 0:9c211972beb2 341
aluqard 0:9c211972beb2 342 do {
aluqard 0:9c211972beb2 343 _sd->rdn((uint8_t*)&de, _sd->o_root + i * 32, sizeof(de));
aluqard 0:9c211972beb2 344 if (0 == memcmp(de.name, dosname, 11))
aluqard 0:9c211972beb2 345 {
aluqard 0:9c211972beb2 346 DEBUGOUT("begin(de)\r\n");
aluqard 0:9c211972beb2 347 begin(de);
aluqard 0:9c211972beb2 348 return 1;
aluqard 0:9c211972beb2 349 }
aluqard 0:9c211972beb2 350 i++;
aluqard 0:9c211972beb2 351 } while (de.name[0]);
aluqard 0:9c211972beb2 352 return 0;
aluqard 0:9c211972beb2 353 }
aluqard 0:9c211972beb2 354
aluqard 0:9c211972beb2 355 void begin(direntry &de)
aluqard 0:9c211972beb2 356 {
aluqard 0:9c211972beb2 357 size = de.size;
aluqard 0:9c211972beb2 358 cluster = de.cluster;
aluqard 0:9c211972beb2 359 if (_sd->type == FAT32)
aluqard 0:9c211972beb2 360 cluster |= ((long)de.cluster_hi << 16);
aluqard 0:9c211972beb2 361 sector = 0;
aluqard 0:9c211972beb2 362 offset = 0;
aluqard 0:9c211972beb2 363 }
aluqard 0:9c211972beb2 364
aluqard 0:9c211972beb2 365 void nextcluster()
aluqard 0:9c211972beb2 366 {
aluqard 0:9c211972beb2 367 if (_sd->type == FAT16)
aluqard 0:9c211972beb2 368 cluster = _sd->rd2(_sd->o_fat + 2 * cluster);
aluqard 0:9c211972beb2 369 else
aluqard 0:9c211972beb2 370 cluster = _sd->rd4(_sd->o_fat + 4 * cluster);
aluqard 0:9c211972beb2 371 #if VERBOSE
aluqard 0:9c211972beb2 372 DEBUGOUT("nextcluster=");
aluqard 0:9c211972beb2 373 DEBUGOUT("%d\r\n", cluster);
aluqard 0:9c211972beb2 374 #endif
aluqard 0:9c211972beb2 375 }
aluqard 0:9c211972beb2 376
aluqard 0:9c211972beb2 377 void skipcluster()
aluqard 0:9c211972beb2 378 {
aluqard 0:9c211972beb2 379 nextcluster();
aluqard 0:9c211972beb2 380 offset += _sd->cluster_size;
aluqard 0:9c211972beb2 381 }
aluqard 0:9c211972beb2 382 void skipsector()
aluqard 0:9c211972beb2 383 {
aluqard 0:9c211972beb2 384 if (sector == _sd->sectors_per_cluster) {
aluqard 0:9c211972beb2 385 sector = 0;
aluqard 0:9c211972beb2 386 nextcluster();
aluqard 0:9c211972beb2 387 }
aluqard 0:9c211972beb2 388 sector++;
aluqard 0:9c211972beb2 389 offset += 512;
aluqard 0:9c211972beb2 390 }
aluqard 0:9c211972beb2 391
aluqard 0:9c211972beb2 392 void seek(uint32_t o)
aluqard 0:9c211972beb2 393 {
aluqard 0:9c211972beb2 394 while (offset < o)
aluqard 0:9c211972beb2 395 {
aluqard 0:9c211972beb2 396 if ((sector == _sd->sectors_per_cluster) && ((o - offset) > (long)_sd->cluster_size))
aluqard 0:9c211972beb2 397 skipcluster();
aluqard 0:9c211972beb2 398 else
aluqard 0:9c211972beb2 399 skipsector();
aluqard 0:9c211972beb2 400 }
aluqard 0:9c211972beb2 401 }
aluqard 0:9c211972beb2 402 void readsector()
aluqard 0:9c211972beb2 403 {
aluqard 0:9c211972beb2 404 if (sector == _sd->sectors_per_cluster)
aluqard 0:9c211972beb2 405 {
aluqard 0:9c211972beb2 406 sector = 0;
aluqard 0:9c211972beb2 407 nextcluster();
aluqard 0:9c211972beb2 408 }
aluqard 0:9c211972beb2 409 uint32_t off = _sd->o_data + ((long)_sd->cluster_size * cluster) + (512L * sector);
aluqard 0:9c211972beb2 410 #if VERBOSE
aluqard 0:9c211972beb2 411 DEBUGOUT("off=0x");
aluqard 0:9c211972beb2 412 DEBUGOUT("%x", off);
aluqard 0:9c211972beb2 413 #endif
aluqard 0:9c211972beb2 414 _sd->cmd17(off & ~511L);
aluqard 0:9c211972beb2 415 // Serial.println(2 * (micros() - t0), DEC);
aluqard 0:9c211972beb2 416 sector++;
aluqard 0:9c211972beb2 417 offset += 512;
aluqard 0:9c211972beb2 418 }
aluqard 0:9c211972beb2 419 void readsector(uint8_t *dst)
aluqard 0:9c211972beb2 420 {
aluqard 0:9c211972beb2 421 readsector();
aluqard 0:9c211972beb2 422 for (int i = 0; i < 64; i++) {
aluqard 0:9c211972beb2 423 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 424 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 425 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 426 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 427 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 428 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 429 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 430 *dst++ = _spi->write(0xff);
aluqard 0:9c211972beb2 431 }
aluqard 0:9c211972beb2 432 _spi->write(0xff); // consume CRC
aluqard 0:9c211972beb2 433 _spi->write(0xff);
aluqard 0:9c211972beb2 434 _sd->desel();
aluqard 0:9c211972beb2 435 }
aluqard 0:9c211972beb2 436 uint32_t cluster;
aluqard 0:9c211972beb2 437 uint32_t offset;
aluqard 0:9c211972beb2 438 uint32_t size;
aluqard 0:9c211972beb2 439 uint8_t sector;
aluqard 0:9c211972beb2 440 };
aluqard 0:9c211972beb2 441
aluqard 0:9c211972beb2 442 class Poly
aluqard 0:9c211972beb2 443 {
aluqard 0:9c211972beb2 444 public:
aluqard 0:9c211972beb2 445 GDClass* _gd;
aluqard 0:9c211972beb2 446 Poly(GDClass* gd)
aluqard 0:9c211972beb2 447 {
aluqard 0:9c211972beb2 448 _gd = gd;
aluqard 0:9c211972beb2 449 }
aluqard 0:9c211972beb2 450
aluqard 0:9c211972beb2 451 int x0, y0, x1, y1;
aluqard 0:9c211972beb2 452 int x[8], y[8];
aluqard 0:9c211972beb2 453 uint8_t n;
aluqard 0:9c211972beb2 454
aluqard 0:9c211972beb2 455 void restart()
aluqard 0:9c211972beb2 456 {
aluqard 0:9c211972beb2 457 n = 0;
aluqard 0:9c211972beb2 458 x0 = 16 * 480;
aluqard 0:9c211972beb2 459 x1 = 0;
aluqard 0:9c211972beb2 460 y0 = 16 * 272;
aluqard 0:9c211972beb2 461 y1 = 0;
aluqard 0:9c211972beb2 462 }
aluqard 0:9c211972beb2 463
aluqard 0:9c211972beb2 464 void perim()
aluqard 0:9c211972beb2 465 {
aluqard 0:9c211972beb2 466 for (uint8_t i = 0; i < n; i++)
aluqard 0:9c211972beb2 467 _gd->Vertex2f(x[i], y[i]);
aluqard 0:9c211972beb2 468 _gd->Vertex2f(x[0], y[0]);
aluqard 0:9c211972beb2 469 }
aluqard 0:9c211972beb2 470 public:
aluqard 0:9c211972beb2 471 void begin()
aluqard 0:9c211972beb2 472 {
aluqard 0:9c211972beb2 473 restart();
aluqard 0:9c211972beb2 474
aluqard 0:9c211972beb2 475 _gd->ColorMask(0,0,0,0);
aluqard 0:9c211972beb2 476 _gd->StencilOp(KEEP, INVERT);
aluqard 0:9c211972beb2 477 _gd->StencilFunc(ALWAYS, 255, 255);
aluqard 0:9c211972beb2 478 }
aluqard 0:9c211972beb2 479
aluqard 0:9c211972beb2 480 void v(int _x, int _y)
aluqard 0:9c211972beb2 481 {
aluqard 0:9c211972beb2 482 x0 = min(x0, _x >> 4);
aluqard 0:9c211972beb2 483 x1 = max(x1, _x >> 4);
aluqard 0:9c211972beb2 484 y0 = min(y0, _y >> 4);
aluqard 0:9c211972beb2 485 y1 = max(y1, _y >> 4);
aluqard 0:9c211972beb2 486 x[n] = _x;
aluqard 0:9c211972beb2 487 y[n] = _y;
aluqard 0:9c211972beb2 488 n++;
aluqard 0:9c211972beb2 489 }
aluqard 0:9c211972beb2 490
aluqard 0:9c211972beb2 491 void paint()
aluqard 0:9c211972beb2 492 {
aluqard 0:9c211972beb2 493 x0 = max(0, x0);
aluqard 0:9c211972beb2 494 y0 = max(0, y0);
aluqard 0:9c211972beb2 495 x1 = min(16 * 480, x1);
aluqard 0:9c211972beb2 496 y1 = min(16 * 272, y1);
aluqard 0:9c211972beb2 497 _gd->ScissorXY(x0, y0);
aluqard 0:9c211972beb2 498 _gd->ScissorSize(x1 - x0 + 1, y1 - y0 + 1);
aluqard 0:9c211972beb2 499 _gd->Begin(EDGE_STRIP_B);
aluqard 0:9c211972beb2 500 perim();
aluqard 0:9c211972beb2 501 }
aluqard 0:9c211972beb2 502
aluqard 0:9c211972beb2 503 void finish()
aluqard 0:9c211972beb2 504 {
aluqard 0:9c211972beb2 505 _gd->ColorMask(1,1,1,1);
aluqard 0:9c211972beb2 506 _gd->StencilFunc(EQUAL, 255, 255);
aluqard 0:9c211972beb2 507
aluqard 0:9c211972beb2 508 _gd->Begin(EDGE_STRIP_B);
aluqard 0:9c211972beb2 509 _gd->Vertex2ii(0, 0);
aluqard 0:9c211972beb2 510 _gd->Vertex2ii(511, 0);
aluqard 0:9c211972beb2 511 }
aluqard 0:9c211972beb2 512
aluqard 0:9c211972beb2 513 void draw()
aluqard 0:9c211972beb2 514 {
aluqard 0:9c211972beb2 515 paint();
aluqard 0:9c211972beb2 516 finish();
aluqard 0:9c211972beb2 517 }
aluqard 0:9c211972beb2 518
aluqard 0:9c211972beb2 519 void outline()
aluqard 0:9c211972beb2 520 {
aluqard 0:9c211972beb2 521 _gd->Begin(LINE_STRIP);
aluqard 0:9c211972beb2 522 perim();
aluqard 0:9c211972beb2 523 }
aluqard 0:9c211972beb2 524 };
aluqard 0:9c211972beb2 525
aluqard 0:9c211972beb2 526 class Streamer
aluqard 0:9c211972beb2 527 {
aluqard 0:9c211972beb2 528 public:
aluqard 0:9c211972beb2 529 GDClass* _gd;
aluqard 0:9c211972beb2 530
aluqard 0:9c211972beb2 531 Streamer(GDClass* gd, sdcard* sd)
aluqard 0:9c211972beb2 532 {
aluqard 0:9c211972beb2 533 r = new Reader(gd->GDTR.SPI(), sd);
aluqard 0:9c211972beb2 534 _gd = gd;
aluqard 0:9c211972beb2 535 }
aluqard 0:9c211972beb2 536 void begin(const char *rawsamples,
aluqard 0:9c211972beb2 537 uint16_t freq = 44100,
aluqard 0:9c211972beb2 538 uint8_t format = ADPCM_SAMPLES,
aluqard 0:9c211972beb2 539 uint32_t _base = (0x40000UL - 8192), uint16_t size = 8192)
aluqard 0:9c211972beb2 540 {
aluqard 0:9c211972beb2 541 r->openfile(rawsamples);
aluqard 0:9c211972beb2 542
aluqard 0:9c211972beb2 543 base = _base;
aluqard 0:9c211972beb2 544 mask = size - 1;
aluqard 0:9c211972beb2 545 wp = 0;
aluqard 0:9c211972beb2 546
aluqard 0:9c211972beb2 547 for (uint8_t i = 10; i; i--)
aluqard 0:9c211972beb2 548 feed();
aluqard 0:9c211972beb2 549
aluqard 0:9c211972beb2 550 _gd->sample(base, size, freq, format, 1);
aluqard 0:9c211972beb2 551 }
aluqard 0:9c211972beb2 552
aluqard 0:9c211972beb2 553 int feed()
aluqard 0:9c211972beb2 554 {
aluqard 0:9c211972beb2 555 uint16_t rp = _gd->rd32(REG_PLAYBACK_READPTR) - base;
aluqard 0:9c211972beb2 556 uint16_t freespace = mask & ((rp - 1) - wp);
aluqard 0:9c211972beb2 557 if (freespace >= 512) {
aluqard 0:9c211972beb2 558 // REPORT(base);
aluqard 0:9c211972beb2 559 // REPORT(rp);
aluqard 0:9c211972beb2 560 // REPORT(wp);
aluqard 0:9c211972beb2 561 // REPORT(freespace);
aluqard 0:9c211972beb2 562 // DEBUGOUT("\r\n");
aluqard 0:9c211972beb2 563 uint8_t buf[512];
aluqard 0:9c211972beb2 564 // uint16_t n = min(512, r->size - r->offset);
aluqard 0:9c211972beb2 565 // n = (n + 3) & ~3; // force 32-bit alignment
aluqard 0:9c211972beb2 566 _gd->__end();
aluqard 0:9c211972beb2 567 r->readsector(buf);
aluqard 0:9c211972beb2 568 _gd->resume();
aluqard 0:9c211972beb2 569 _gd->cmd_memwrite(base + wp, 512);
aluqard 0:9c211972beb2 570 _gd->copyram(buf, 512);
aluqard 0:9c211972beb2 571 wp = (wp + 512) & mask;
aluqard 0:9c211972beb2 572 }
aluqard 0:9c211972beb2 573 return r->offset < r->size;
aluqard 0:9c211972beb2 574 }
aluqard 0:9c211972beb2 575
aluqard 0:9c211972beb2 576 void progress(uint16_t &val, uint16_t &range)
aluqard 0:9c211972beb2 577 {
aluqard 0:9c211972beb2 578 uint32_t m = r->size;
aluqard 0:9c211972beb2 579 uint32_t p = min(r->offset, m);
aluqard 0:9c211972beb2 580 while (m > 0x10000) {
aluqard 0:9c211972beb2 581 m >>= 1;
aluqard 0:9c211972beb2 582 p >>= 1;
aluqard 0:9c211972beb2 583 }
aluqard 0:9c211972beb2 584 val = p;
aluqard 0:9c211972beb2 585 range = m;
aluqard 0:9c211972beb2 586 }
aluqard 0:9c211972beb2 587 private:
aluqard 0:9c211972beb2 588 Reader* r;
aluqard 0:9c211972beb2 589 uint32_t base;
aluqard 0:9c211972beb2 590 uint16_t mask;
aluqard 0:9c211972beb2 591 uint16_t wp;
aluqard 0:9c211972beb2 592 };
aluqard 0:9c211972beb2 593
aluqard 0:9c211972beb2 594
aluqard 0:9c211972beb2 595 static uint8_t sinus(GDClass* gd, uint8_t x)
aluqard 0:9c211972beb2 596 {
aluqard 0:9c211972beb2 597 return 128 + gd->rsin(128, -16384 + (x << 7));
aluqard 0:9c211972beb2 598 }
aluqard 0:9c211972beb2 599
aluqard 0:9c211972beb2 600 #endif