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-21
- Revision:
- 6:a4dff59ef214
- Parent:
- 5:367397a82ddc
- Child:
- 7:2ac6752d47d2
File content as of revision 6:a4dff59ef214:
#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); } ErrorType pl_error=None; enum WordType { Unknown, Number, Word, Quote }; uint8_t *pl_codeblock; int pl_blockpos; int pl_blocksize; void 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++; } void 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++; } void 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; } void 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; } void new_codeblock(bool freeit) { if(freeit) { free(pl_codeblock); } pl_codeblock=(uint8_t*)malloc(CODEBLOCKSTEP); pl_blockpos=0; pl_blocksize=CODEBLOCKSTEP; } int execute_codeblock() { return forth_execute(pl_codeblock, pl_blockpos); } 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]==';') { //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]=='!'){ int tmp=pl_pop(); int* tmp2=(int*)pl_pop(); *tmp2=tmp; }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(strlcmp("if", word, 3)==0){ }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)){ 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, MAXCALLS, 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; }