2 * Milkymist VJ SoC (Software)
3 * Copyright (C) 2007, 2008, 2009, 2010 Sebastien Bourdeauducq
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
30 #include <hw/sysctl.h>
32 #include <hw/interrupts.h>
49 #define NUMBER_OF_BYTES_ON_A_LINE 16
50 static void dump_bytes(unsigned int *ptr, int count, unsigned addr)
52 char *data = (char *)ptr;
53 int line_bytes = 0, i = 0;
55 putsnonl("Memory dump:");
58 (count > NUMBER_OF_BYTES_ON_A_LINE)?
59 NUMBER_OF_BYTES_ON_A_LINE : count;
61 printf("\n0x%08x ", addr);
62 for(i=0;i<line_bytes;i++)
63 printf("%02x ", *(unsigned char *)(data+i));
65 for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
70 for(i=0;i<line_bytes;i++) {
71 if((*(data+i) < 0x20) || (*(data+i) > 0x7e))
74 printf("%c", *(data+i));
77 for(;i<NUMBER_OF_BYTES_ON_A_LINE;i++)
80 data += (char)line_bytes;
87 static void mr(char *startaddr, char *len)
94 printf("mr <address> [length]\n");
97 addr = (unsigned *)strtoul(startaddr, &c, 0);
99 printf("incorrect address\n");
105 length = strtoul(len, &c, 0);
107 printf("incorrect length\n");
112 dump_bytes(addr, length, (unsigned)addr);
115 static void mw(char *addr, char *value, char *count)
123 if((*addr == 0) || (*value == 0)) {
124 printf("mw <address> <value>\n");
127 addr2 = (unsigned *)strtoul(addr, &c, 0);
129 printf("incorrect address\n");
132 value2 = strtoul(value, &c, 0);
134 printf("incorrect value\n");
140 count2 = strtoul(count, &c, 0);
142 printf("incorrect count\n");
146 for (i=0;i<count2;i++) *addr2++ = value2;
149 static int lscb(const char *filename, const char *longname, void *param)
151 printf("%12s [%s]\n", filename, longname);
158 cffat_list_files(lscb, NULL);
162 static void render(const char *filename)
165 printf("render <filename>\n");
169 ui_render_from_file(filename, 0);
174 spam_enabled = !spam_enabled;
176 printf("Advertising enabled\n");
178 printf("Advertising disabled\n");
183 int hours, mins, secs;
192 printf("Uptime: %02d:%02d:%02d FPS: %d CPU:%3d%%\n", hours, mins, secs,
199 puts("Milkymist demo firmware\n");
200 puts("Available commands :");
201 puts("mr - read address space");
202 puts("mw - write address space");
203 puts("flush - flush FML bridge cache");
204 puts("ls - list files on the memory card");
205 puts("render - start rendering a preset");
206 puts("stop - stop renderer");
207 puts("spam - start/stop advertising");
208 puts("stats - print system stats");
209 puts("reboot - system reset");
210 puts("mdior - read MDIO register");
211 puts("mdiow - write MDIO register");
214 static void mdior(char *reg)
220 printf("mdior <register>\n");
223 reg2 = strtoul(reg, &c, 0);
225 printf("incorrect register\n");
229 printf("%02x\n", mdio_read(0, reg2));
232 static void mdiow(char *reg, char *value)
238 if((*reg == 0) || (*value == 0)) {
239 printf("mdiow <register> <value>\n");
242 reg2 = strtoul(reg, &c, 0);
244 printf("incorrect address\n");
247 value2 = strtoul(value, &c, 0);
249 printf("incorrect value\n");
253 mdio_write(0, reg2, value2);
257 static void loadpic(const char *filename)
262 printf("loadpic <filename>\n");
266 if(!cffat_init()) return;
267 if(!cffat_load(filename, (void *)vga_backbuffer, vga_hres*vga_vres*2, &size)) return;
273 static void checker()
277 for(y=0;y<vga_vres;y++)
278 for(x=0;x<vga_hres;x++)
280 vga_backbuffer[y*vga_hres+x] = 0x0000;
282 vga_backbuffer[y*vga_hres+x] = 0xffff;
287 * Low-level PFPU test, bypassing driver.
288 * This test should only be run when the driver task queue
291 static struct tmu_vertex mesh[128][128] __attribute__((aligned(8)));
292 static void pfputest()
294 unsigned int *pfpu_regs = (unsigned int *)CSR_PFPU_DREGBASE;
295 unsigned int *pfpu_code = (unsigned int *)CSR_PFPU_CODEBASE;
298 unsigned int oldmask;
300 /* Do not let the driver get our interrupt */
301 oldmask = irq_getmask();
302 irq_setmask(oldmask & (~IRQ_PFPU));
306 mesh[y][x].x = 0xdeadbeef;
307 mesh[y][x].y = 0xdeadbeef;
310 CSR_PFPU_MESHBASE = (unsigned int)&mesh;
311 //CSR_PFPU_HMESHLAST = 6;
312 //CSR_PFPU_VMESHLAST = 9;
314 CSR_PFPU_HMESHLAST = 11;
315 CSR_PFPU_VMESHLAST = 9;
317 pfpu_regs[3] = 0x41300000;
318 pfpu_regs[4] = 0x41100000;
320 pfpu_code[ 0] = 0x00000300;
321 pfpu_code[ 1] = 0x00040300;
322 pfpu_code[ 2] = 0x00000000;
323 pfpu_code[ 3] = 0x00000003;
324 pfpu_code[ 4] = 0x00000004;
325 pfpu_code[ 5] = 0x000c2080;
326 pfpu_code[ 6] = 0x00000000;
327 pfpu_code[ 7] = 0x00000000;
328 pfpu_code[ 8] = 0x00000000;
329 pfpu_code[ 9] = 0x00000005;
330 pfpu_code[10] = 0x00142b80;
332 CSR_PFPU_CTL = PFPU_CTL_START;
333 printf("Waiting for PFPU...\n");
336 printf("%08x vertices:%d collisions:%d strays:%d last:%08x pc:%04x\n",
337 CSR_PFPU_CTL, CSR_PFPU_VERTICES, CSR_PFPU_COLLISIONS, CSR_PFPU_STRAYWRITES, CSR_PFPU_LASTDMA, 4*CSR_PFPU_PC);
338 } while((timeout--) && (CSR_PFPU_CTL & PFPU_CTL_BUSY));
344 asm volatile( /* Invalidate Level-1 data cache */
352 printf("%08x ", mesh[y][x].x);
358 printf("%08x ", mesh[y][x].y);
362 printf("Program:\n");
364 printf("%08x ", pfpu_code[x]);
367 CSR_PFPU_CTL = 0; /* Ack interrupt */
369 irq_setmask(oldmask);
372 static void tmutest_callback(struct tmu_td *td)
375 complete = (int *)td->user;
379 static void tmutest()
382 static struct tmu_vertex srcmesh[TMU_MESH_MAXSIZE][TMU_MESH_MAXSIZE] __attribute__((aligned(8)));
384 volatile int complete;
388 srcmesh[y][x].x = (10*x) << TMU_FIXEDPOINT_SHIFT;
389 srcmesh[y][x].y = (7*y) << TMU_FIXEDPOINT_SHIFT;
395 td.brightness = TMU_BRIGHTNESS_MAX;
397 td.vertices = &srcmesh[0][0];
398 td.texfbuf = vga_frontbuffer;
399 td.texhres = vga_hres;
400 td.texvres = vga_vres;
401 td.texhmask = TMU_MASK_FULL;
402 td.texvmask = TMU_MASK_FULL;
403 td.dstfbuf = vga_backbuffer;
404 td.dsthres = vga_hres;
405 td.dstvres = vga_vres;
408 td.dstsquarew = vga_hres/32;
409 td.dstsquareh = vga_vres/32;
411 td.callback = tmutest_callback;
412 td.user = (void *)&complete;
415 flush_bridge_cache();
416 tmu_submit_task(&td);
421 static unsigned short original[640*480*2] __attribute__((aligned(2)));
423 static void tmudemo()
426 unsigned int oldmask;
427 static struct tmu_vertex srcmesh[TMU_MESH_MAXSIZE][TMU_MESH_MAXSIZE] __attribute__((aligned(8)));
429 volatile int complete;
431 int mindelta, xdelta, ydelta;
433 if(!cffat_init()) return;
434 if(!cffat_load("lena.raw", (void *)original, vga_hres*vga_vres*2, &size)) return;
439 /* Disable UI keys and slowout */
440 oldmask = irq_getmask();
441 irq_setmask(oldmask & (~IRQ_GPIO) & (~IRQ_TIMER1));
444 w = 512 << TMU_FIXEDPOINT_SHIFT;
449 srcmesh[0][0].x = xdelta;
450 srcmesh[0][0].y = ydelta;
451 srcmesh[0][1].x = w+xdelta;
452 srcmesh[0][1].y = ydelta;
453 srcmesh[1][0].x = xdelta;
454 srcmesh[1][0].y = w+ydelta;
455 srcmesh[1][1].x = w+xdelta;
456 srcmesh[1][1].y = w+ydelta;
458 if(CSR_GPIO_IN & GPIO_DIP6) {
459 if(CSR_GPIO_IN & GPIO_PBN)
461 if(CSR_GPIO_IN & GPIO_PBS)
463 if(CSR_GPIO_IN & GPIO_PBE)
465 if(CSR_GPIO_IN & GPIO_PBW)
468 if(CSR_GPIO_IN & GPIO_PBN)
470 if(CSR_GPIO_IN & GPIO_PBS)
482 if(w > ((TMU_MASK_FULL >> 1)+mindelta)) {
483 w = (TMU_MASK_FULL >> 1)+mindelta;
486 if(speed > 0) speed--;
487 if(speed < 0) speed++;
493 td.brightness = TMU_BRIGHTNESS_MAX;
495 td.vertices = &srcmesh[0][0];
496 td.texfbuf = original;
497 td.texhres = vga_hres;
498 td.texvres = vga_vres;
499 td.texhmask = CSR_GPIO_IN & GPIO_DIP7 ? 0x7FFF : TMU_MASK_FULL;
500 td.texvmask = CSR_GPIO_IN & GPIO_DIP8 ? 0x7FFF : TMU_MASK_FULL;
501 td.dstfbuf = vga_backbuffer;
502 td.dsthres = vga_hres;
503 td.dstvres = vga_vres;
506 td.dstsquarew = vga_hres;
507 td.dstsquareh = vga_vres;
509 td.callback = tmutest_callback;
510 td.user = (void *)&complete;
513 flush_bridge_cache();
514 CSR_TIMER1_CONTROL = 0;
515 CSR_TIMER1_COUNTER = 0;
516 CSR_TIMER1_COMPARE = 0xffffffff;
517 CSR_TIMER1_CONTROL = TIMER_ENABLE;
518 tmu_submit_task(&td);
520 CSR_TIMER1_CONTROL = 0;
522 if(readchar_nonblock()) {
528 t = CSR_TIMER1_COUNTER;
529 printf("Processing cycles: %d (%d Mpixels/s)\n", t, 640*480*100/t);
535 irq_setmask(oldmask);
538 static short audio_buffer1[SND_MAX_NSAMPLES*2];
539 static short audio_buffer2[SND_MAX_NSAMPLES*2];
540 static short audio_buffer3[SND_MAX_NSAMPLES*2];
541 static short audio_buffer4[SND_MAX_NSAMPLES*2];
543 static void record_callback(short *buffer, void *user)
545 snd_play_refill(buffer);
548 static void play_callback(short *buffer, void *user)
550 snd_record_refill(buffer);
555 if(snd_play_active()) {
558 printf("Digital Echo demo stopped\n");
563 for(i=0;i<AC97_MAX_DMASIZE/2;i++) {
564 audio_buffer1[i] = 0;
565 audio_buffer2[i] = 0;
567 snd_play_refill(audio_buffer1);
568 snd_play_refill(audio_buffer2);
569 snd_play_start(play_callback, SND_MAX_NSAMPLES, NULL);
572 snd_record_refill(audio_buffer3);
573 snd_record_refill(audio_buffer4);
574 snd_record_start(record_callback, SND_MAX_NSAMPLES, NULL);
575 printf("Digital Echo demo started\n");
579 static char *get_token(char **str)
583 c = (char *)strchr(*str, ' ');
586 *str = *str+strlen(*str);
595 static void do_command(char *c)
597 char *command, *param1, *param2, *param3;
599 command = get_token(&c);
600 param1 = get_token(&c);
601 param2 = get_token(&c);
602 param3 = get_token(&c);
604 if(strcmp(command, "mr") == 0) mr(param1, param2);
605 else if(strcmp(command, "mw") == 0) mw(param1, param2, param3);
606 else if(strcmp(command, "ls") == 0) ls();
607 else if(strcmp(command, "flush") == 0) flush_bridge_cache();
608 else if(strcmp(command, "render") == 0) render(param1);
609 else if(strcmp(command, "stop") == 0) ui_render_stop();
610 else if(strcmp(command, "spam") == 0) spam();
611 else if(strcmp(command, "stats") == 0) stats();
612 else if(strcmp(command, "reboot") == 0) reboot();
613 else if(strcmp(command, "help") == 0) help();
616 else if(strcmp(command, "mdior") == 0) mdior(param1);
617 else if(strcmp(command, "mdiow") == 0) mdiow(param1, param2);
619 /* Test functions and hacks */
620 else if(strcmp(command, "loadpic") == 0) loadpic(param1);
621 else if(strcmp(command, "checker") == 0) checker();
622 else if(strcmp(command, "pfputest") == 0) pfputest();
623 else if(strcmp(command, "tmutest") == 0) tmutest();
624 else if(strcmp(command, "tmudemo") == 0) tmudemo();
625 else if(strcmp(command, "echo") == 0) echo();
627 else if(strcmp(command, "") != 0) printf("Command not found: '%s'\n", command);
630 static char command_buffer[64];
631 static unsigned int command_index;
635 putsnonl("\e[1m% \e[0m");
644 void shell_input(char c)
650 if(command_index > 0) {
652 putsnonl("\x08 \x08");
657 command_buffer[command_index] = 0x00;
660 do_command(command_buffer);
664 if(command_index < (sizeof(command_buffer)-1)) {
666 command_buffer[command_index] = c;