A project to implement a console using the Mbed using VGA for video output and a PS/2 keyboard for the input. The eventual goal is to also include tools for managing SD cards, and a semi-self-hosting programming environment.
Dependencies: PS2_MbedConsole fastlib SDFileSystem vga640x480g_mbedconsole lightvm mbed
MbedConsole is a cool little project to have a self-contained computer all on an Mbed. So far it has VGA and PS/2 support and can stand alone without a computer powering it. Next planned features are SD card support and a lightweight programmable VM complete with a file editor and self-hosted assembler.
You can view additional details about it at http://earlz.net/tags/mbedconsole
plEarlz.cpp
- Committer:
- earlz
- Date:
- 2012-09-28
- Revision:
- 11:fede136943a9
- Parent:
- 9:4211d638b2e9
- Child:
- 16:370b9e559f92
File content as of revision 11:fede136943a9:
#include "mbedconsole.h" #include "plEarlz.h" #include <stdarg.h> #include <stdint.h> //Basically a non-conforming take on Forth, btw. inline int internal_captureline(void* pBuffer, char const* pFormatString, ...) { char* pStringEnd = (char*)pBuffer + strlen((char*)pBuffer); va_list valist; va_start(valist, pFormatString); return vsprintf(pStringEnd, pFormatString, valist); } void printheapstats() { char buffer[256]; __heapstats(internal_captureline, buffer); vputs("Memory info: "); vputs(buffer); } BranchTarget *last_target=NULL; ErrorType pl_error=None; enum WordType { Unknown, Number, Word, Quote }; uint8_t *pl_codeblock; int pl_blockpos; int pl_blocksize; uint8_t* push_opcode_byte(uint8_t val) { if(pl_blockpos>=pl_blocksize) { void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); if(tmp==NULL) { vputs("Out of memory!!"); return; } pl_codeblock=(uint8_t*)tmp; pl_blocksize+=CODEBLOCKSTEP; } pl_codeblock[pl_blockpos]=val; pl_blockpos++; return &pl_codeblock[pl_blockpos-1]; } Opcode* push_opcode(Opcode val) { if(pl_blockpos>=pl_blocksize) { void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); if(tmp==NULL) { vputs("Out of memory!!"); return; } pl_codeblock=(uint8_t*)tmp; pl_blocksize+=CODEBLOCKSTEP; } pl_codeblock[pl_blockpos]=(uint8_t)val; pl_blockpos++; return (Opcode*)&pl_codeblock[pl_blockpos-1]; } uint16_t* push_opcode_word(uint16_t val) { if(pl_blockpos>=pl_blocksize) { void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); if(tmp==NULL) { vputs("Out of memory!!"); return; } pl_codeblock=(uint8_t*)tmp; pl_blocksize+=CODEBLOCKSTEP; } *(uint16_t*)&pl_codeblock[pl_blockpos]=val; pl_blockpos+=2; return (uint16_t*)(&pl_codeblock[pl_blockpos-2]); } uint32_t* push_opcode_dword(uint32_t val) { if(pl_blockpos>=pl_blocksize) { void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP); if(tmp==NULL) { vputs("Out of memory!!"); return; } pl_codeblock=(uint8_t*)tmp; pl_blocksize+=CODEBLOCKSTEP; } *(uint32_t*)&pl_codeblock[pl_blockpos]=val; pl_blockpos+=4; return (uint32_t*)&pl_codeblock[pl_blockpos-4]; } void new_codeblock(bool freeit) { if(freeit) { free(pl_codeblock); } pl_codeblock=(uint8_t*)malloc(CODEBLOCKSTEP); pl_blockpos=0; pl_blocksize=CODEBLOCKSTEP; last_target=NULL; } int execute_codeblock() { return forth_execute(pl_codeblock, pl_blockpos); } void push_target(int address) { BranchTarget* target=(BranchTarget*)malloc(sizeof(BranchTarget)); target->previous=last_target; target->target=address; last_target=target; } void pop_target() { if(last_target==NULL) { vputs("Unmatched control statement!\n"); return; } volatile void* tmp=last_target; last_target=last_target->previous; free((void*)tmp); } inline void write_blockword(int pos,uint16_t val) { *(uint16_t*)&pl_codeblock[pos]=val; } int compile_word(char *word, WordType type) //returns 0 for success, 1 for ending word found, -1 for error { if(type==Number){ push_opcode(Push); push_opcode_dword(atoi(word)); }else{ if(word[1]==0) //check the quick builtins first { if(word[0]=='.'){ push_opcode(CallInt); push_opcode_dword((uint32_t)&bi_print); }else if(word[0]==';') { push_opcode(Ret); //execute! return 1; }else if(word[0]=='+'){ push_opcode(Add); }else if(word[0]=='/'){ push_opcode(Div); }else if(word[0]=='-'){ push_opcode(Sub); }else if(word[0]=='!'){ //pl_push(pl_pop()-pl_pop()); }else if(word[0]=='%'){ push_opcode(Mod); }else if(word[0]=='*'){ push_opcode(Mul); }else if(word[0]=='!'){ //push_opcode(Store); }else if(word[0]=='?'){ pl_push(*(int*)pl_pop()); }else if(word[0]=='='){ pl_push(pl_pop() == pl_pop()); }else if(word[0]=='`'){ pl_push(pl_pop()>0); }else if(word[0]=='$'){ //print string (address on stack }else if(word[0]=='['){ //begin quotation push_opcode(Push); push_opcode_word(pl_blockpos+3); push_opcode(Branch); push_target(pl_blockpos); push_opcode_word(0); }else if(word[0] == ']'){ //end quotation push_opcode(Ret); write_blockword(last_target->target, pl_blockpos); pop_target(); } }else if(strlcmp("if", word, 3)==0){ push_opcode(BranchFalse); push_target(pl_blockpos); push_opcode_word(0); }else if(strlcmp("else", word, 5)==0){ push_opcode(Branch); int tmp=pl_blockpos; push_opcode_word(0); write_blockword(last_target->target,pl_blockpos); pop_target(); push_target(tmp); //have to do it after we pop it or we fall into an infinite loop! }else if(strlcmp("end", word, 4)==0){ write_blockword(last_target->target,(uint16_t)pl_blockpos); pop_target(); }else if(strlcmp("tif", word, 4)==0){ /** swap value 2 behind stack to front call.true 1 from stack call.false top of stack _label: **/ //alloca(10); push_opcode(Push); push_opcode_dword(3); push_opcode(Pick); push_opcode(BranchFalse); //push_opcode_word(pl_blockpos+ }else{ vputs("I don't know the word '"); vputs(word); vputs("'\n"); } } return 0; } void parse_line(char *line) { int len=strlen(line); char word[16]; word[0]=0; int wordpos=0; WordType type=Unknown; for(int i=0;i<len;i++) { char c=line[i]; if(is_whitespace(c) || c=='\\') { if(word[0]!=0) { word[wordpos]=0; int tmp=compile_word(word,type); if(tmp==1) { execute_codeblock(); new_codeblock(true); } word[0]=0; } wordpos=0; type=Unknown; if(c=='\\'){ return; //rest is a comment } }else if(is_numeric(c)){ if(type==Unknown){ type=Number; } word[wordpos]=c; wordpos++; }else if(is_quote(c)){ push_opcode(LoadStr); for(;i<len;i++) { //char c=line[ } vputs("This isn't supported yet foo!"); return; }else{ if(type==Number){ vputs("Syntax Error! Unexpected symbol in the middle of a number"); return; } type=Word; word[wordpos]=c; wordpos++; } } } void tester() { printf("foo!"); } int pl_shell() { vputs(">>plEarlz -- A forth-ish shell<<\n"); printheapstats(); vputs("\n"); char *line=(char*)malloc(MAXLINELENGTH); sprintf(line, "Stack Size: %i; Max Recursion Level %i; Loaded WORDs: %i", MAXSTACK, MAXTEMPSTACK, 0); vputs(line); sprintf(line, "Max line length: %i\n", MAXLINELENGTH); vputs(line); new_codeblock(false); char *tmp=(char*)malloc(32); //for constructing words/elements while(1) { vputs("cmd> "); vgetsl(line, MAXLINELENGTH); line[MAXLINELENGTH-1]=0; int len=strlen(line); line[len]='\n'; line[len+1]=0; parse_line(line); } free(line); free(tmp); return 0; }