Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: ConfigFile FATFileSystem mbed
Revision 1:e74530ad6b9e, committed 2015-05-13
- Comitter:
- va009039
- Date:
- Wed May 13 18:39:01 2015 +0900
- Parent:
- 0:25fe9b2fe195
- Child:
- 2:908338b1151a
- Commit message:
- add L152RE.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseIPS.cpp Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,743 @@
+// BaseIPS.cpp 2015/5/6
+#include "mbed.h"
+#include "BaseIPS.h"
+
+#include <math.h>
+#define Round(x) ( (x>=0) ? (int)(x+0.5) : (int)(x-0.5) )
+
+BaseIPS::BaseIPS() {
+ PS = 0xfff8;
+ RS = 0x4f8;
+ depth=0;
+ idle=0;
+ input_ptr = 512;
+ cycle = 0;
+ inputfile = NULL;
+}
+
+u16 BaseIPS::peek(u16 a) {
+ return peekB(a) | peekB(a + 1)<<8;
+}
+
+void BaseIPS::poke(u16 a, u16 w) {
+ pokeB(a, w & 0xff);
+ pokeB(a + 1, w>>8);
+}
+
+u32 BaseIPS::peek32(u16 a) {
+ return peekB(a) | peekB(a + 1)<<8 | peekB(a + 2)<<16 | peekB(a + 3)<<24;
+}
+
+
+void BaseIPS::push_ps(u16 w) {
+ PS -= 2;
+ poke(PS, w);
+}
+
+u16 BaseIPS::pull_ps() {
+ PS += 2;
+ return peek(PS - 2);
+}
+
+void BaseIPS::push_rs(u16 w) {
+ RS -= 2;
+ poke(RS, w);
+}
+
+u16 BaseIPS::pull_rs() {
+ RS += 2;
+ return peek(RS - 2);
+}
+
+void BaseIPS::c_rumpelstilzchen(void) { // 0
+}
+
+void BaseIPS::c_defex(void) { // 1
+ push_rs(PPC);
+ PPC = HP;
+ depth++;
+}
+
+void BaseIPS::c_consex(void) { // 2
+ push_ps(peek(HP));
+}
+
+void BaseIPS::c_varex(void) { // 3
+ push_ps(HP);
+}
+
+void BaseIPS::c_retex(void) { // 4
+ depth--;
+ PPC = pull_rs();
+}
+
+void BaseIPS::c_get(void) { // 5
+ poke(PS, peek(peek(PS)));
+}
+
+void BaseIPS::c_getB(void) { // 6
+ poke(PS, peekB(peek(PS)));
+}
+
+void BaseIPS::c_put(void) { // 7
+ u16 a = pull_ps();
+ u16 v = pull_ps();
+ if (peek(a) != v) idle=0;
+ poke(a, v);
+}
+
+void BaseIPS::c_putB(void) { // 8
+ u16 a = pull_ps();
+ u16 v = pull_ps();
+ if (peekB(a) != v) idle=0;
+ pokeB(a, v);
+ idle=0;
+}
+
+void BaseIPS::c_1bliteral(void) { // 9
+ push_ps(peekB(PPC));
+ PPC++;
+}
+
+void BaseIPS::c_2bliteral(void) { // 10
+ push_ps(peek(PPC));
+ PPC += 2;
+}
+
+void BaseIPS::c_bronz(void) { // 11
+ if ((pull_ps() & 1) == 0) PPC=peek(PPC);
+ else PPC += 2;
+}
+
+void BaseIPS::c_jump(void) { // 12
+ PPC = peek(PPC);
+}
+
+void BaseIPS::c_weg(void) { // 13
+ PS += 2;
+}
+
+void BaseIPS::c_pweg(void) { // 14
+ PS += 4;
+}
+
+void BaseIPS::c_plus(void) { // 15
+ s16 v = pull_ps();
+ poke(PS, peek(PS) + v);
+}
+
+void BaseIPS::c_minus(void) { // 16
+ s16 v = pull_ps();
+ poke(PS, peek(PS) - v);
+}
+
+void BaseIPS::c_dup(void) { // 17
+ push_ps(peek(PS));
+}
+
+void BaseIPS::c_pdup(void) { // 18
+ push_ps(peek(PS + 2));
+ push_ps(peek(PS + 2));
+}
+
+void BaseIPS::c_vert(void) { // 19
+ s16 h=peek(PS);
+ poke(PS, peek(PS + 2));
+ poke(PS + 2, h);
+}
+
+void BaseIPS::c_zwo(void) { // 20
+ push_ps(peek(PS+2));
+}
+
+void BaseIPS::c_rdu(void) { // 21
+ s16 h=peek(PS);
+ poke(PS, peek(PS+2));
+ poke(PS+2, peek(PS+4));
+ poke(PS+4, h);
+}
+
+void BaseIPS::c_rdo(void) { // 22
+ s16 h=peek(PS+4);
+ poke(PS+4, peek(PS+2));
+ poke(PS+2, peek(PS));
+ poke(PS, h);
+}
+
+void BaseIPS::c_index(void) { // 23
+ push_ps(peek(RS));
+}
+
+void BaseIPS::c_s_to_r(void) { // 24
+ push_rs(pull_ps());
+}
+
+void BaseIPS::c_r_to_s(void) { // 25
+ push_ps(pull_rs());
+}
+
+void BaseIPS::c_eqz(void) { // 26
+ poke(PS,(peek(PS)==0));
+}
+
+void BaseIPS::c_gz(void) { // 27
+ poke(PS,((s16)peek(PS)>0));
+}
+
+void BaseIPS::c_lz(void) { // 28
+ poke(PS,((s16)peek(PS)<0));
+}
+
+void BaseIPS::c_geu(void) { // 29
+ u16 a,b;
+ b=pull_ps();
+ a=peek(PS);
+ poke(PS,a>=b);
+}
+
+void BaseIPS::c_f_vergl(void) { // 30
+ int t;
+ u16 n,a1,a2;
+ n=pull_ps();
+ a2=pull_ps();
+ a1=peek(PS);
+ t=1;
+ do {
+ int b;
+ b=(s16)peekB(a1++)-(s16)peekB(a2++);
+ if (b>0) t=2;
+ else if (b<0) t=0;
+ n=(n-1)&0xff;
+ } while (n);
+ poke(PS,t);
+}
+
+void BaseIPS::c_nicht(void) { // 31
+ poke(PS, 0xffff^peek(PS));
+}
+
+void BaseIPS::c_und(void) { // 32
+ u16 v = pull_ps();
+ poke(PS, v & peek(PS));
+}
+
+void BaseIPS::c_oder(void) { // 33
+ u16 v = pull_ps();
+ poke(PS, v | peek(PS));
+}
+
+void BaseIPS::c_exo(void) { // 34
+ u16 v = pull_ps();
+ poke(PS, v ^ peek(PS));
+}
+
+void BaseIPS::c_bit(void) { // 35
+ poke(PS, 1<<peek(PS));
+}
+
+void BaseIPS::c_cbit(void) { // 36
+ int a = pull_ps();
+ int b = (pull_ps())&0x07;
+ pokeB(a, peekB(a)&~(1<<b) );
+}
+
+void BaseIPS::c_sbit(void) { // 37
+ int a,b;
+ a=pull_ps();
+ b=(pull_ps())&0x07;
+ pokeB(a, peekB(a)|(1<<b) );
+}
+
+void BaseIPS::c_tbit(void) { // 38
+ int a,b;
+ a=pull_ps();
+ b=(peek(PS))&0x07;
+ if (peekB(a)&(1<<b)) poke(PS,1);
+ else poke(PS,0);
+}
+
+void BaseIPS::loop_sharedcode(int i) {
+ int l;
+ l=(s16)peek(RS);
+ if (i<=l) {
+ push_rs(i);
+ PPC=peek(PPC);
+ } else {
+ pull_rs();
+ PPC+=2;
+ }
+}
+
+void BaseIPS::c_jeex(void) { // 39
+ PPC=peek(PPC);
+ push_rs(pull_ps());
+ loop_sharedcode((s16)pull_ps());
+}
+
+void BaseIPS::c_loopex(void) { // 40
+ loop_sharedcode((s16)(pull_rs()+1));
+}
+
+void BaseIPS::c_plusloopex(void) { // 41
+ int i;
+ i=(s16)(pull_rs());
+ loop_sharedcode(i+(s16)pull_rs());
+}
+
+void BaseIPS::c_fieldtrans(void) { // 42
+ /* note: cannot call memcpy() here, because memcpy()'s behaviour is not defined when source and destination areas overlap */
+ /* memmove() cannot be used either, because its behaviour for overlap is different from what IPS expects */
+ int n,d,s,b;
+ n=pull_ps();
+ d=pull_ps();
+ s=pull_ps();
+ do {
+ b=peekB(s++);
+ pokeB(d++,b);
+ n=(n-1)&0xff;
+ } while (n);
+ if (d<=0x400) redraw=1;
+ idle=0;
+}
+
+void BaseIPS::c_pmul(void) { // 43
+ u32 c = pull_ps() * pull_ps();
+ push_ps((s16)(c&0xffff));
+ push_ps(c>>16);
+}
+
+void BaseIPS::c_pdiv(void) { // 44
+ u32 q,n;
+ u16 d,nh,nl,r;
+ d=pull_ps();
+ nh=pull_ps();
+ nl=pull_ps();
+ n=(nh<<16)+nl;
+ if (d==0) { q=0xffff; r=0; }
+ else {
+ q=n/d;
+ r=n%d;
+ if (q>=0x10000) { q=0xffff; r=0; }
+ }
+ push_ps(q);
+ push_ps(r);
+}
+
+void BaseIPS::c_tue(void) { // 45
+ HP = pull_ps();
+}
+
+void BaseIPS::c_polyname(void) { // 46
+ u32 x,p,d;
+ d=pull_ps();
+ x=pull_ps();
+ p=pull_ps();
+ x= x | (p&0xff00) | ((p&0xff)<<16);
+ p = d ^ x ^ (x>>1) ^ (x>>2) ^ (x>>7);
+ x = x ^ ((p&0xff)<<24);
+ x >>= 7;
+ push_ps( (x&0xff00) | ((x>>16)&0xff) );
+ push_ps( (x&0xff) );
+}
+
+void BaseIPS::c_scode(void) { // 47
+ int i;
+ u32 nd;
+ int offs=peek(a_Os);
+ i=peek(a_NDptr);
+ nd=peek32(i);
+ i=peek(a_P3);
+ while (i) {
+ i+=offs;
+ if ( ( (peek32(i) ^ nd) & 0xffffff3f) ==0) {
+ push_ps(i+6);
+ return;
+ }
+ i=peek(i+4);
+ }
+ push_ps(0);
+}
+
+void BaseIPS::c_cscan(void) { // 48
+ int a;
+ int pi,pe;
+ int comment=0;
+ pi=peek(a_PI);
+ pe=peek(a_PE);
+
+ a=pull_ps();
+ if (a==1) {
+ while (pi<=pe) {
+ if (comment) {
+ if (peekB(pi)==')') comment=0;
+ } else {
+ if (peekB(pi)=='(') comment=1;
+ else if (peekB(pi)!=' ') {
+ poke(a_PI,pi);
+ push_ps(1);
+ return;
+ }
+ }
+ pi++;
+ }
+ push_ps(0);
+ poke(a_P2,1);
+ return;
+ } else {
+ while (pi<=pe) {
+ if (peekB(pi)==' ') {
+ break;
+ }
+ pi++;
+ }
+ poke(a_PI,pi);
+ push_ps(0);
+ }
+}
+
+void BaseIPS::c_chs(void) { // 49
+ poke(PS,-(s16)peek(PS));
+}
+
+void BaseIPS::c_cyc2(void) { // 50
+ u32 ch,a,crcc;
+ int i;
+
+ ch=pull_ps();
+ a=pull_ps();
+ crcc=(a>>8)|((a&0xff)<<8);
+
+ ch<<=8;
+ for (i=0;i<=7;i++) {
+ //int test;
+ //test=(ch^crcc)&0x8000;
+ crcc<<=1;
+ ch<<=1;
+ if ((ch^crcc)&0x10000) crcc^=0x1021;
+ }
+
+ push_ps( ((crcc&0xff)<<8) | ((crcc>>8)&0xff) );
+}
+
+void BaseIPS::c_close(void) { // 51
+ if (inputfile) {
+ file_close(inputfile);
+ inputfile = NULL;
+ }
+}
+
+void BaseIPS::c_open(void) { // 52
+ if (inputfile) {
+ file_close(inputfile);
+ }
+ int namelen = pull_ps();
+ int namestart = pull_ps();
+ char filename[256];
+ if (namelen > sizeof(filename)-1) {
+ namelen = sizeof(filename) - 1;
+ }
+ for(int i = 0; i < namelen; i++) {
+ filename[i] = peekB(namestart + i);
+ }
+ filename[namelen] = '\0';
+ inputfile = file_open(filename);
+ push_ps(inputfile != NULL ? 1 : 0);
+}
+
+void BaseIPS::c_oscli(void) { // 53
+ error("OSCLI not implemented!");
+}
+
+void BaseIPS::c_load(void) { // 54
+ error("LOAD not implemented!");
+}
+
+void BaseIPS::c_save(void) { // 55
+ int namelen = pull_ps();
+ int namestart = pull_ps();
+ int end = pull_ps();
+ int start = pull_ps();
+
+ char filename[256];
+ if (namelen > 255) namelen = 255;
+ for(int i = 0; i < namelen; i++) {
+ filename[i] = peekB(namestart + i);
+ }
+ filename[namelen] = 0;
+
+ void* fh = file_open(filename, "wb");
+ if (fh == NULL) {
+ push_ps(0);
+ return;
+ }
+ for(int i = start; i < end; i++) {
+ file_putc(peekB(i), fh);
+ }
+ file_close(fh);
+ push_ps(1);
+}
+
+void BaseIPS::c_setkbptr(void) { // 56
+ input_ptr = pull_ps() & 0x3ff;
+}
+
+void BaseIPS::c_getPS(void) { // 57
+ push_ps(PS);
+}
+
+void BaseIPS::c_setPS(void) { // 58
+ PS=pull_ps();
+}
+
+void BaseIPS::c_rp_code(void) { // 59
+ double theta,x,y,r;
+ pull_ps();
+ y=(s16)pull_ps();
+ x=(s16)pull_ps();
+ theta=((s16)pull_ps())/10430.38; /* convert to radians */
+ theta+=atan2(y,x);
+ r=sqrt(x*x+y*y)*1.6468;
+ push_ps(Round(theta*10430.38));
+ push_ps((int)(r+0.5));
+ push_ps(0);
+}
+
+void BaseIPS::c_tr_code(void) { // 60
+ double theta,x,y,r;
+ pull_ps();
+ y=(s16)pull_ps();
+ x=(s16)pull_ps();
+ theta=((s16)pull_ps())/10430.38; /* convert to radians */
+ theta+=atan2(y,x);
+ r=sqrt(x*x+y*y)*1.6468;
+ push_ps(0);
+ push_ps(Round(r*cos(theta)));
+ push_ps(Round(r*sin(theta)));
+}
+
+void BaseIPS::c_swap3(void) { // 61
+ u16 h;
+ h=peek(PS+6); poke(PS+6,peek(PS)); poke(PS,h);
+ h=peek(PS+8); poke(PS+8,peek(PS+2)); poke(PS+2,h);
+ h=peek(PS+10); poke(PS+10,peek(PS+4)); poke(PS+4,h);
+}
+
+void BaseIPS::c_defchar(void) { // 62
+ error("DEFCHAR not implemented!\n");
+}
+
+void BaseIPS::c_pplus(void) { // 63
+ u32 h=pull_ps();
+ u32 b=(h<<16)+pull_ps();
+ h=pull_ps();
+ u32 a=(h<<16)+pull_ps();
+ u32 c=a+b;
+ push_ps(c&0xffff);
+ push_ps(c>>16);
+}
+
+void BaseIPS::c_pminus(void) { // 64
+ u32 h = pull_ps();
+ u32 b = (h<<16)+pull_ps();
+ h = pull_ps();
+ u32 a = (h<<16)+pull_ps();
+ u32 c = a - b;
+ push_ps(c&0xffff);
+ push_ps(c>>16);
+}
+
+void BaseIPS::c_sleepifidle(void) { // 80
+/* extension for IPS-Mu, i.e., the linux/unix version */
+ if (idle) {
+ //do_sleep();
+ //leaveloop=0;
+ }
+ idle=1;
+}
+
+void BaseIPS::do_20ms(void) {
+ pokeB(UHR, peekB(UHR) + 2); // 20ms
+ if (peekB(UHR) == 100) {
+ pokeB(UHR, 0);
+ pokeB(UHR+1, peekB(UHR+1) + 1);
+ if (peekB(UHR+1) == 60) {
+ pokeB(UHR+1, 0);
+ pokeB(UHR+2, peekB(UHR+2) + 1);
+ if (peekB(UHR+2) == 60) {
+ pokeB(UHR+2, 0);
+ pokeB(UHR+3, peekB(UHR+3) + 1);
+ if (peekB(UHR+3) == 24) {
+ pokeB(UHR+3, 0);
+ poke(UHR+4, peek(UHR+4) + 1);
+ }
+ }
+ }
+ }
+
+ const int sus[4]={SU0,SU1,SU2,SU3};
+ for (int i = 0; i < 4; i++) {
+ int su=sus[i];
+ if ((peekB(su)&1) == 0) {
+ if (peekB(su) != 0) {
+ pokeB(su, peekB(su) - 2);
+ } else {
+ if (peekB(su+1) != 0) {
+ pokeB(su, 98);
+ pokeB(su+1, peekB(su+1) - 1);
+ } else {
+ if (peekB(su+2) != 0) {
+ pokeB(su+1, 59);
+ pokeB(su+2, peekB(su+2) - 1);
+ } else {
+ if (peekB(su+3) != 0) {
+ pokeB(su+2, 255);
+ pokeB(su+3, peekB(su+3) - 1);
+ } else {
+ pokeB(su, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void BaseIPS::read_inputfile(void) {
+ for(int i = 0x200; i < 0x400; i++) {
+ pokeB(i, ' ');
+ }
+
+ do {
+ int ch = file_getc(inputfile);
+ if (ch<1) {
+ if (input_ptr == peek(a_PI)) {
+ file_close(inputfile);
+ inputfile = NULL;
+ pokeB(LOADFLAG, 0);
+ input_ptr = 0x200;
+ }
+ break;
+ }
+ if (ch=='\r') {
+ /* ignore \r, we expect at least also a \n as end-of-line */
+ } else if (ch=='\n') {
+ input_ptr=(input_ptr&0xffc0)+64;
+ } else {
+ pokeB(input_ptr++,ch);
+ }
+ } while (input_ptr<1024 && inputfile); /* 1024 = TVE */
+
+ if (input_ptr!=peek(a_PI)) {
+ pokeB(READYFLAG,1);
+ poke(a_PE,input_ptr-1);
+ idle=0;
+ }
+}
+
+void BaseIPS::emulator() {
+ PPC = 0x0400;
+ input_ptr = peek(a_PI);
+ while(1) {
+ HP = peek(PPC);
+ PPC += 2;
+exec: u16 CPC = peek(HP);
+ HP += 2;
+ trace(cycle++, PPC-2, HP-2, CPC, PS, RS);
+ switch(CPC) {
+ case 1: c_defex(); break;
+ case 2: c_consex(); break;
+ case 3: c_varex(); break;
+ case 4: c_retex(); break;
+ case 5: c_get(); break;
+ case 6: c_getB(); break;
+ case 7: c_put(); break;
+ case 8: c_putB(); break;
+ case 9: c_1bliteral(); break;
+ case 10: c_2bliteral(); break;
+ case 11: c_bronz(); break;
+ case 12: c_jump(); break;
+ case 13: c_weg(); break;
+ case 14: c_pweg(); break;
+ case 15: c_plus(); break;
+ case 16: c_minus(); break;
+ case 17: c_dup(); break;
+ case 18: c_pdup(); break;
+ case 19: c_vert(); break;
+ case 20: c_zwo(); break;
+ case 21: c_rdu(); break;
+ case 22: c_rdo(); break;
+ case 23: c_index(); break;
+ case 24: c_s_to_r(); break;
+ case 25: c_r_to_s(); break;
+ case 26: c_eqz(); break;
+ case 27: c_gz(); break;
+ case 28: c_lz(); break;
+ case 29: c_geu(); break;
+ case 30: c_f_vergl(); break;
+ case 31: c_nicht(); break;
+ case 32: c_und(); break;
+ case 33: c_oder(); break;
+ case 34: c_exo(); break;
+ case 35: c_bit(); break;
+ case 36: c_cbit(); break;
+ case 37: c_sbit(); break;
+ case 38: c_tbit(); break;
+ case 39: c_jeex(); break;
+ case 40: c_loopex(); break;
+ case 41: c_plusloopex(); break;
+ case 42: c_fieldtrans(); break;
+ case 43: c_pmul(); break;
+ case 44: c_pdiv(); break;
+ case 45: c_tue(); goto exec;
+ case 46: c_polyname(); break;
+ case 47: c_scode(); break;
+ case 48: c_cscan(); break;
+ case 49: c_chs(); break;
+ case 50: c_cyc2(); break;
+ case 51: c_close(); break;
+ case 52: c_open(); break;
+ case 53: c_oscli(); break;
+ case 54: c_load(); break;
+ case 55: c_save(); break;
+ case 56: c_setkbptr(); break;
+ case 57: c_getPS(); break;
+ case 58: c_setPS(); break;
+ case 59: c_rp_code(); break;
+ case 60: c_tr_code(); break;
+ case 61: c_swap3(); break;
+ case 62: c_defchar(); break;
+ case 63: c_pplus(); break;
+ case 64: c_pminus(); break;
+ case 80: c_sleepifidle(); break;
+ default: c_rumpelstilzchen(); break;
+ }
+ do_io();
+ if (test_20ms()) {
+ do_20ms();
+ }
+ if (inputfile) {
+ if (!(peekB(READYFLAG)&1) && (peekB(LOADFLAG)&1)) {
+ read_inputfile();
+ }
+ }
+ }
+}
+
+void BaseIPS::load_image(const u8* image, int size) {
+ for(int i = 0; i < size; i++) {
+ pokeB(i, *image++);
+ }
+}
+
+void BaseIPS::command(const char* s) {
+ if (s) {
+ int cmd_len = strlen(s);
+ for(int i = 0; i < cmd_len; i++) {
+ pokeB(i + 64*8, *s++);
+ }
+ poke(a_PE, 0x200 + cmd_len);
+ pokeB(READYFLAG, 1);
+ }
+}
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/BaseIPS.h Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,134 @@
+// BaseIPS.h 2015/5/6
+#pragma once
+
+/* data types */
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef signed short s16;
+typedef unsigned long u32;
+typedef unsigned char byte;
+
+/* some variables of IPS also need to be accessed by the emulator; here are their addresses: */
+#define READYFLAG 0x42e
+#define LOADFLAG 0x43b
+#define UHR 0x418
+#define SU0 0x41e
+#define SU1 0x422
+#define SU2 0x426
+#define SU3 0x42a
+#define a_PE 0x42f
+#define a_PI 0x431
+#define a_P1 0x433
+#define a_P2 0x435
+#define a_P3 0x437
+#define a_NDptr 0x43e
+#define a_Os 0x43c
+
+#define TVE 1023
+
+class BaseIPS {
+public:
+ BaseIPS();
+ void emulator();
+ void load_image(const u8* image, int size);
+ void command(const char* s);
+
+protected:
+ virtual u8 peekB(u16 a) = 0;
+ virtual void pokeB(u16 a, u8 b) = 0;
+ void poke(u16 a, u16 w);
+ u16 peek(u16 a);
+ virtual void do_io() = 0;
+ virtual bool test_20ms() { return false; }
+ virtual void* file_open(const char* filename, const char* mode = "rb") { return NULL; }
+ virtual int file_getc(void* handle) { return -1; }
+ virtual void file_putc(int c, void* handle) {}
+ virtual bool file_close(void* handle) { return false; }
+ virtual void trace(u32 cycle, u16 ppc, u16 hp, u16 cpc, u16 ps, u16 rs) {}
+ int input_ptr;
+
+private:
+ u32 peek32(u16 a);
+ u16 PPC, HP, PS, RS;
+ u32 cycle;
+ int depth;
+ int redraw;
+ int idle;
+ void push_ps(u16 w);
+ u16 pull_ps();
+ void push_rs(u16 w);
+ u16 pull_rs();
+ void* inputfile;
+ void do_20ms();
+ void read_inputfile(void);
+
+ void c_rumpelstilzchen(void); // 0
+ void c_defex(void); // 1
+ void c_consex(void); // 2
+ void c_varex(void); // 3
+ void c_retex(void); // 4
+ void c_get(void); // 5
+ void c_getB(void); // 6
+ void c_put(void); // 7
+ void c_putB(void); // 8
+ void c_1bliteral(void); // 9
+ void c_2bliteral(void); // 10
+ void c_bronz(void); // 11
+ void c_jump(void); // 12
+ void c_weg(void); // 13
+ void c_pweg(void); // 14
+ void c_plus(void); // 15
+ void c_minus(void); // 16
+ void c_dup(void); // 17
+ void c_pdup(void); // 18
+ void c_vert(void); // 19
+ void c_zwo(void); // 20
+ void c_rdu(void); // 21
+ void c_rdo(void); // 22
+ void c_index(void); // 23
+ void c_s_to_r(void); // 24
+ void c_r_to_s(void); // 25
+ void c_eqz(void); // 26
+ void c_gz(void); // 27
+ void c_lz(void); // 28
+ void c_geu(void); // 29
+ void c_f_vergl(void); // 30
+ void c_nicht(void); // 31
+ void c_und(void); // 32
+ void c_oder(void); // 33
+ void c_exo(void); // 34
+ void c_bit(void); // 35
+ void c_cbit(void); // 36
+ void c_sbit(void); // 37
+ void c_tbit(void); // 38
+ void loop_sharedcode(int i);
+ void c_jeex(void); // 39
+ void c_loopex(void); // 40
+ void c_plusloopex(void); // 41
+ void c_fieldtrans(void); // 42
+ void c_pmul(void); // 43
+ void c_pdiv(void); // 44
+ void c_tue(void); // 45
+ void c_polyname(void); // 46
+ void c_scode(void); // 47
+ void c_cscan(void); // 48
+ void c_chs(void); // 49
+ void c_cyc2(void); // 50
+ void c_close(void); // 51
+ void c_open(void); // 52
+ void c_oscli(void); // 53
+ void c_load(void); // 54
+ void c_save(void); // 55
+ void c_setkbptr(void); // 56
+ void c_getPS(void); // 57
+ void c_setPS(void); // 58
+ void c_rp_code(void); // 59
+ void c_tr_code(void); // 60
+ void c_swap3(void); // 61
+ void c_defchar(void); // 62
+ void c_pplus(void); // 63
+ void c_pminus(void); // 64
+ void c_sleepifidle(void); // 80
+};
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem/SDFileSystem.cpp Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,498 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2012 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+/* Introduction
+ * ------------
+ * SD and MMC cards support a number of interfaces, but common to them all
+ * is one based on SPI. This is the one I'm implmenting because it means
+ * it is much more portable even though not so performant, and we already
+ * have the mbed SPI Interface!
+ *
+ * The main reference I'm using is Chapter 7, "SPI Mode" of:
+ * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
+ *
+ * SPI Startup
+ * -----------
+ * The SD card powers up in SD mode. The SPI interface mode is selected by
+ * asserting CS low and sending the reset command (CMD0). The card will
+ * respond with a (R1) response.
+ *
+ * CMD8 is optionally sent to determine the voltage range supported, and
+ * indirectly determine whether it is a version 1.x SD/non-SD card or
+ * version 2.x. I'll just ignore this for now.
+ *
+ * ACMD41 is repeatedly issued to initialise the card, until "in idle"
+ * (bit 0) of the R1 response goes to '0', indicating it is initialised.
+ *
+ * You should also indicate whether the host supports High Capicity cards,
+ * and check whether the card is high capacity - i'll also ignore this
+ *
+ * SPI Protocol
+ * ------------
+ * The SD SPI protocol is based on transactions made up of 8-bit words, with
+ * the host starting every bus transaction by asserting the CS signal low. The
+ * card always responds to commands, data blocks and errors.
+ *
+ * The protocol supports a CRC, but by default it is off (except for the
+ * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
+ * I'll leave the CRC off I think!
+ *
+ * Standard capacity cards have variable data block sizes, whereas High
+ * Capacity cards fix the size of data block to 512 bytes. I'll therefore
+ * just always use the Standard Capacity cards with a block size of 512 bytes.
+ * This is set with CMD16.
+ *
+ * You can read and write single blocks (CMD17, CMD25) or multiple blocks
+ * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
+ * the card gets a read command, it responds with a response token, and then
+ * a data token or an error.
+ *
+ * SPI Command Format
+ * ------------------
+ * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
+ *
+ * +---------------+------------+------------+-----------+----------+--------------+
+ * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
+ * +---------------+------------+------------+-----------+----------+--------------+
+ *
+ * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
+ *
+ * All Application Specific commands shall be preceded with APP_CMD (CMD55).
+ *
+ * SPI Response Format
+ * -------------------
+ * The main response format (R1) is a status byte (normally zero). Key flags:
+ * idle - 1 if the card is in an idle state/initialising
+ * cmd - 1 if an illegal command code was detected
+ *
+ * +-------------------------------------------------+
+ * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
+ * +-------------------------------------------------+
+ *
+ * R1b is the same, except it is followed by a busy signal (zeros) until
+ * the first non-zero byte when it is ready again.
+ *
+ * Data Response Token
+ * -------------------
+ * Every data block written to the card is acknowledged by a byte
+ * response token
+ *
+ * +----------------------+
+ * | xxx | 0 | status | 1 |
+ * +----------------------+
+ * 010 - OK!
+ * 101 - CRC Error
+ * 110 - Write Error
+ *
+ * Single Block Read and Write
+ * ---------------------------
+ *
+ * Block transfers have a byte header, followed by the data, followed
+ * by a 16-bit CRC. In our case, the data will always be 512 bytes.
+ *
+ * +------+---------+---------+- - - -+---------+-----------+----------+
+ * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
+ * +------+---------+---------+- - - -+---------+-----------+----------+
+ */
+#include "SDFileSystem.h"
+#include "mbed_debug.h"
+
+#define SD_COMMAND_TIMEOUT 5000
+
+#define SD_DBG 0
+
+SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
+ FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0) {
+ _cs = 1;
+
+ // Set default to 100kHz for initialisation and 1MHz for data transfer
+ _init_sck = 100000;
+ _transfer_sck = 1000000;
+}
+
+#define R1_IDLE_STATE (1 << 0)
+#define R1_ERASE_RESET (1 << 1)
+#define R1_ILLEGAL_COMMAND (1 << 2)
+#define R1_COM_CRC_ERROR (1 << 3)
+#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
+#define R1_ADDRESS_ERROR (1 << 5)
+#define R1_PARAMETER_ERROR (1 << 6)
+
+// Types
+// - v1.x Standard Capacity
+// - v2.x Standard Capacity
+// - v2.x High Capacity
+// - Not recognised as an SD Card
+#define SDCARD_FAIL 0
+#define SDCARD_V1 1
+#define SDCARD_V2 2
+#define SDCARD_V2HC 3
+
+int SDFileSystem::initialise_card() {
+ // Set to SCK for initialisation, and clock card with cs = 1
+ _spi.frequency(_init_sck);
+ _cs = 1;
+ for (int i = 0; i < 16; i++) {
+ _spi.write(0xFF);
+ }
+
+ // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
+ if (_cmd(0, 0) != R1_IDLE_STATE) {
+ debug("No disk, or could not put SD card in to SPI idle state\n");
+ return SDCARD_FAIL;
+ }
+
+ // send CMD8 to determine whther it is ver 2.x
+ int r = _cmd8();
+ if (r == R1_IDLE_STATE) {
+ return initialise_card_v2();
+ } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
+ return initialise_card_v1();
+ } else {
+ debug("Not in idle state after sending CMD8 (not an SD card?)\n");
+ return SDCARD_FAIL;
+ }
+}
+
+int SDFileSystem::initialise_card_v1() {
+ for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+ _cmd(55, 0);
+ if (_cmd(41, 0) == 0) {
+ cdv = 512;
+ debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r");
+ return SDCARD_V1;
+ }
+ }
+
+ debug("Timeout waiting for v1.x card\n");
+ return SDCARD_FAIL;
+}
+
+int SDFileSystem::initialise_card_v2() {
+ for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+ wait_ms(50);
+ _cmd58();
+ _cmd(55, 0);
+ if (_cmd(41, 0x40000000) == 0) {
+ _cmd58();
+ debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r");
+ cdv = 1;
+ return SDCARD_V2;
+ }
+ }
+
+ debug("Timeout waiting for v2.x card\n");
+ return SDCARD_FAIL;
+}
+
+int SDFileSystem::disk_initialize() {
+ _is_initialized = initialise_card();
+ if (_is_initialized == 0) {
+ debug("Fail to initialize card\n");
+ return 1;
+ }
+ debug_if(SD_DBG, "init card = %d\n", _is_initialized);
+ _sectors = _sd_sectors();
+
+ // Set block length to 512 (CMD16)
+ if (_cmd(16, 512) != 0) {
+ debug("Set 512-byte block timed out\n");
+ return 1;
+ }
+
+ // Set SCK for data transfer
+ _spi.frequency(_transfer_sck);
+ return 0;
+}
+
+int SDFileSystem::disk_write(const uint8_t* buffer, uint64_t block_number, uint8_t count) {
+ if (!_is_initialized) {
+ return -1;
+ }
+
+ for (uint64_t b = block_number; b < block_number + count; b++) {
+ // set write address for single block (CMD24)
+ if (_cmd(24, b * cdv) != 0) {
+ return 1;
+ }
+
+ // send the data block
+ _write(buffer, 512);
+ buffer += 512;
+ }
+
+ return 0;
+}
+
+int SDFileSystem::disk_read(uint8_t* buffer, uint64_t block_number, uint8_t count) {
+ if (!_is_initialized) {
+ return -1;
+ }
+
+ for (uint64_t b = block_number; b < block_number + count; b++) {
+ // set read address for single block (CMD17)
+ if (_cmd(17, b * cdv) != 0) {
+ return 1;
+ }
+
+ // receive the data
+ _read(buffer, 512);
+ buffer += 512;
+ }
+
+ return 0;
+}
+
+int SDFileSystem::disk_status() {
+ // FATFileSystem::disk_status() returns 0 when initialized
+ if (_is_initialized) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+int SDFileSystem::disk_sync() { return 0; }
+uint64_t SDFileSystem::disk_sectors() { return _sectors; }
+
+
+// PRIVATE FUNCTIONS
+int SDFileSystem::_cmd(int cmd, int arg) {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | cmd);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if (!(response & 0x80)) {
+ _cs = 1;
+ _spi.write(0xFF);
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+int SDFileSystem::_cmdx(int cmd, int arg) {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | cmd);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if (!(response & 0x80)) {
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+
+int SDFileSystem::_cmd58() {
+ _cs = 0;
+ int arg = 0;
+
+ // send a command
+ _spi.write(0x40 | 58);
+ _spi.write(arg >> 24);
+ _spi.write(arg >> 16);
+ _spi.write(arg >> 8);
+ _spi.write(arg >> 0);
+ _spi.write(0x95);
+
+ // wait for the repsonse (response[7] == 0)
+ for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
+ int response = _spi.write(0xFF);
+ if (!(response & 0x80)) {
+ int ocr = _spi.write(0xFF) << 24;
+ ocr |= _spi.write(0xFF) << 16;
+ ocr |= _spi.write(0xFF) << 8;
+ ocr |= _spi.write(0xFF) << 0;
+ _cs = 1;
+ _spi.write(0xFF);
+ return response;
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+int SDFileSystem::_cmd8() {
+ _cs = 0;
+
+ // send a command
+ _spi.write(0x40 | 8); // CMD8
+ _spi.write(0x00); // reserved
+ _spi.write(0x00); // reserved
+ _spi.write(0x01); // 3.3v
+ _spi.write(0xAA); // check pattern
+ _spi.write(0x87); // crc
+
+ // wait for the repsonse (response[7] == 0)
+ for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
+ char response[5];
+ response[0] = _spi.write(0xFF);
+ if (!(response[0] & 0x80)) {
+ for (int j = 1; j < 5; j++) {
+ response[i] = _spi.write(0xFF);
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return response[0];
+ }
+ }
+ _cs = 1;
+ _spi.write(0xFF);
+ return -1; // timeout
+}
+
+int SDFileSystem::_read(uint8_t *buffer, uint32_t length) {
+ _cs = 0;
+
+ // read until start byte (0xFF)
+ while (_spi.write(0xFF) != 0xFE);
+
+ // read data
+ for (uint32_t i = 0; i < length; i++) {
+ buffer[i] = _spi.write(0xFF);
+ }
+ _spi.write(0xFF); // checksum
+ _spi.write(0xFF);
+
+ _cs = 1;
+ _spi.write(0xFF);
+ return 0;
+}
+
+int SDFileSystem::_write(const uint8_t*buffer, uint32_t length) {
+ _cs = 0;
+
+ // indicate start of block
+ _spi.write(0xFE);
+
+ // write the data
+ for (uint32_t i = 0; i < length; i++) {
+ _spi.write(buffer[i]);
+ }
+
+ // write the checksum
+ _spi.write(0xFF);
+ _spi.write(0xFF);
+
+ // check the response token
+ if ((_spi.write(0xFF) & 0x1F) != 0x05) {
+ _cs = 1;
+ _spi.write(0xFF);
+ return 1;
+ }
+
+ // wait for write to finish
+ while (_spi.write(0xFF) == 0);
+
+ _cs = 1;
+ _spi.write(0xFF);
+ return 0;
+}
+
+static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
+ uint32_t bits = 0;
+ uint32_t size = 1 + msb - lsb;
+ for (uint32_t i = 0; i < size; i++) {
+ uint32_t position = lsb + i;
+ uint32_t byte = 15 - (position >> 3);
+ uint32_t bit = position & 0x7;
+ uint32_t value = (data[byte] >> bit) & 1;
+ bits |= value << i;
+ }
+ return bits;
+}
+
+uint64_t SDFileSystem::_sd_sectors() {
+ uint32_t c_size, c_size_mult, read_bl_len;
+ uint32_t block_len, mult, blocknr, capacity;
+ uint32_t hc_c_size;
+ uint64_t blocks;
+
+ // CMD9, Response R2 (R1 byte + 16-byte block read)
+ if (_cmdx(9, 0) != 0) {
+ debug("Didn't get a response from the disk\n");
+ return 0;
+ }
+
+ uint8_t csd[16];
+ if (_read(csd, 16) != 0) {
+ debug("Couldn't read csd response from disk\n");
+ return 0;
+ }
+
+ // csd_structure : csd[127:126]
+ // c_size : csd[73:62]
+ // c_size_mult : csd[49:47]
+ // read_bl_len : csd[83:80] - the *maximum* read block length
+
+ int csd_structure = ext_bits(csd, 127, 126);
+
+ switch (csd_structure) {
+ case 0:
+ cdv = 512;
+ c_size = ext_bits(csd, 73, 62);
+ c_size_mult = ext_bits(csd, 49, 47);
+ read_bl_len = ext_bits(csd, 83, 80);
+
+ block_len = 1 << read_bl_len;
+ mult = 1 << (c_size_mult + 2);
+ blocknr = (c_size + 1) * mult;
+ capacity = blocknr * block_len;
+ blocks = capacity / 512;
+ debug_if(SD_DBG, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
+ break;
+
+ case 1:
+ cdv = 1;
+ hc_c_size = ext_bits(csd, 63, 48);
+ blocks = (hc_c_size+1)*1024;
+ debug_if(SD_DBG, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks);
+ break;
+
+ default:
+ debug("CSD struct unsupported\r\n");
+ return 0;
+ };
+ return blocks;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem/SDFileSystem.h Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,89 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2012 ARM Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#ifndef MBED_SDFILESYSTEM_H
+#define MBED_SDFILESYSTEM_H
+
+#include "mbed.h"
+#include "FATFileSystem.h"
+#include <stdint.h>
+
+/** Access the filesystem on an SD Card using SPI
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "SDFileSystem.h"
+ *
+ * SDFileSystem sd(p5, p6, p7, p12, "sd"); // mosi, miso, sclk, cs
+ *
+ * int main() {
+ * FILE *fp = fopen("/sd/myfile.txt", "w");
+ * fprintf(fp, "Hello World!\n");
+ * fclose(fp);
+ * }
+ */
+class SDFileSystem : public FATFileSystem {
+public:
+
+ /** Create the File System for accessing an SD Card using SPI
+ *
+ * @param mosi SPI mosi pin connected to SD Card
+ * @param miso SPI miso pin conencted to SD Card
+ * @param sclk SPI sclk pin connected to SD Card
+ * @param cs DigitalOut pin used as SD Card chip select
+ * @param name The name used to access the virtual filesystem
+ */
+ SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name);
+ virtual int disk_initialize();
+ virtual int disk_status();
+ virtual int disk_read(uint8_t* buffer, uint64_t block_number, uint8_t count);
+ virtual int disk_write(const uint8_t* buffer, uint64_t block_number, uint8_t count);
+ virtual int disk_sync();
+ virtual uint64_t disk_sectors();
+
+protected:
+
+ int _cmd(int cmd, int arg);
+ int _cmdx(int cmd, int arg);
+ int _cmd8();
+ int _cmd58();
+ int initialise_card();
+ int initialise_card_v1();
+ int initialise_card_v2();
+
+ int _read(uint8_t * buffer, uint32_t length);
+ int _write(const uint8_t *buffer, uint32_t length);
+ uint64_t _sd_sectors();
+ uint64_t _sectors;
+
+ void set_init_sck(uint32_t sck) { _init_sck = sck; }
+ // Note: The highest SPI clock rate is 20 MHz for MMC and 25 MHz for SD
+ void set_transfer_sck(uint32_t sck) { _transfer_sck = sck; }
+ uint32_t _init_sck;
+ uint32_t _transfer_sck;
+
+ SPI _spi;
+ DigitalOut _cs;
+ int cdv;
+ int _is_initialized;
+};
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VideoRAM.h Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,34 @@
+#pragma once
+
+class VideoRAM {
+public:
+ VideoRAM(RawSerial& pc):_pc(pc),x(0),y(0) {
+ _puts("\x1b[2J"); // erase
+ }
+ void vpoke(uint16_t i, uint8_t b) {
+ if (i < 1024) {
+ if (x != i%64 || y != i/64) {
+ x = i%64;
+ y = i/64;
+ char buf[16];
+ snprintf(buf, sizeof(buf), "\x1b[%d;%dH", y+1, x+1) ; // locate
+ _puts(buf);
+ }
+ _putc(b & 0x7f);
+ x++;
+ }
+ }
+
+private:
+ void _puts(const char* s) {
+ while(*s) {
+ _putc(*s++);
+ }
+ }
+ void _putc(int c) {
+ _pc.putc(c);
+ }
+ RawSerial& _pc;
+ uint16_t x, y;
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/VirtualRAM.h Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,37 @@
+// VirtualRAM.h 2015/4/29
+#pragma once
+#define PAGE_CHUNK_SIZE 1024
+class VirtualRAM {
+public:
+ int used_size;
+ VirtualRAM(): used_size(0) {
+ memset(mem_ptr, 0x00, sizeof(mem_ptr)); // NULL
+ }
+ uint8_t peek(uint16_t a) {
+ uint8_t* mem = ptr(a);
+ if (mem == NULL) {
+ return 0x00;
+ }
+ return mem[a % PAGE_CHUNK_SIZE];
+ }
+ void poke(uint16_t a, uint8_t b) {
+ uint8_t* mem = ptr(a);
+ if (mem == NULL) {
+ mem = reinterpret_cast<uint8_t*>(malloc(PAGE_CHUNK_SIZE));
+ MBED_ASSERT(mem != NULL);
+ mem_ptr[idx(a)] = mem;
+ used_size += PAGE_CHUNK_SIZE;
+ }
+ mem[a % PAGE_CHUNK_SIZE] = b;
+ }
+
+private:
+ uint8_t* ptr(uint16_t addr) {
+ return mem_ptr[idx(addr)];
+ }
+ int idx(uint16_t addr) {
+ return addr / PAGE_CHUNK_SIZE;
+ }
+ uint8_t* mem_ptr[65536 / PAGE_CHUNK_SIZE];
+};
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Wed May 13 18:39:01 2015 +0900
@@ -0,0 +1,124 @@
+// main.cpp 2015/5/13
+#include "mbed.h"
+#include "BaseIPS.h"
+#include "VideoRAM.h"
+#include "VirtualRAM.h"
+#include "SDFileSystem.h"
+#include "ConfigFile.h"
+#include <string>
+
+#define CFG_FILE "/local/ips.cfg"
+
+#ifndef MBED_SPI0
+#define MBED_SPI0 D11, D12, D13, D4
+#endif
+SDFileSystem local(MBED_SPI0, "local"); // mosi, miso, sclk, cs, name
+
+RawSerial pc(USBTX,USBRX);
+
+class myips : public BaseIPS {
+ VideoRAM vram;
+ VirtualRAM mem;
+ RawSerial& _pc;
+ Timer t20ms;
+public:
+ myips(RawSerial& pc): vram(pc),_pc(pc) {
+ t20ms.reset();
+ t20ms.start();
+ }
+ virtual u8 peekB(u16 a) {
+ return mem.peek(a);
+ }
+ virtual void pokeB(u16 a, u8 b) {
+ mem.poke(a, b);
+ vram.vpoke(a, b);
+ }
+ virtual void* file_open(const char* filename, const char* mode) {
+ string path = string("/local/") + filename;
+ return fopen(path.c_str(), mode);
+ }
+ virtual int file_getc(void* handle) {
+ MBED_ASSERT(handle);
+ int c = fgetc((FILE*)handle);
+ return c == EOF ? (-1) : c;
+ }
+ virtual void file_putc(int c, void* handle) {
+ MBED_ASSERT(handle);
+ fputc(c, (FILE*)handle);
+ }
+ virtual bool file_close(void* handle) {
+ MBED_ASSERT(handle);
+ if (fclose((FILE*)handle) == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool test_20ms() {
+ if (t20ms.read_ms() >= 20) {
+ t20ms.reset();
+ return true;
+ }
+ return false;
+ }
+
+ virtual void do_io() {
+ if (_pc.readable()) {
+ int c = _pc.getc();
+ if (c == '\n' || c == '\r') {
+ if (input_ptr != peek(a_PI)) {
+ pokeB(READYFLAG, 1);
+ poke(a_PE, input_ptr - 1);
+ }
+ else if (c == 0x08) // BS
+ if (input_ptr > 0) {
+ input_ptr--;
+ }
+ } else {
+ if (input_ptr <= TVE) {
+ pokeB(input_ptr++, c);
+ }
+ }
+ }
+ }
+};
+
+int main() {
+ string image = "IPS-Mu.bin";
+ string file;
+ string cmd;
+ ConfigFile cfg;
+ if(cfg.read(CFG_FILE)) {
+ char buf[128];
+ if (cfg.getValue("image", buf, sizeof(buf))) {
+ image = buf;
+ }
+ if (cfg.getValue("file", buf, sizeof(buf))) {
+ file = buf;
+ cmd = string("\" ") + file + string(" \" READ");
+ }
+ if (cfg.getValue("cmd", buf, sizeof(buf))) {
+ cmd = buf;
+ }
+ }
+
+ myips* ips = new myips(pc);
+ void* fh = ips->file_open(image.c_str(), "rb");
+ MBED_ASSERT(fh);
+ if (fh) {
+ for(int i = 0; i <= 65535; i++) {
+ int c = ips->file_getc(fh);
+ if (c == (-1)) {
+ break;
+ }
+ ips->pokeB(i, c);
+ }
+ ips->file_close(fh);
+ }
+ if (cmd != "") {
+ ips->command(cmd.c_str());
+ }
+ ips->emulator();
+ /* NOTREACHED */
+}
+