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-20
- Revision:
- 5:367397a82ddc
- Parent:
- 4:b44c27404035
- Child:
- 6:a4dff59ef214
File content as of revision 5:367397a82ddc:
#include "mbedconsole.h" #include "plEarlz.h" #include <stdarg.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); } struct pl_word { }; #define MAXSTACK 64 #define MAXCALLS 32 #define MAXLINELENGTH 128 #define DICTIONARYSTEP 4 //how much memory to reserve when doing a reallocation for resizing int pl_stackpos=0; int pl_stack[MAXSTACK]; enum ErrorType { None, StackOverflow, StackUnderflow }; ErrorType pl_error=None; //int *pl_callstack[MAXCALLS]; enum WordType { Unknown, Number, Word, Quote }; typedef void (*BuiltinFunction)(void); typedef struct { char name[12]; enum Type{ Constant, ConstantString, Builtin, Function } type; union valueunion{ int intvalue; BuiltinFunction builtin; char *string; } value; } WordKey; int pl_dictionary_count=0; int pl_dictionary_size=0; WordKey *pl_dictionary; //todo: a hash table would be much faster void pl_push(int val) { if(pl_stackpos>=MAXSTACK) { vputs("Stack overflow!"); pl_error=StackOverflow; return; } pl_stack[pl_stackpos]=val; pl_stackpos++; } int pl_pop() { if(pl_stackpos<=0) { vputs("Stack underflow!"); pl_error=StackUnderflow; return 0; } pl_stackpos--; return pl_stack[pl_stackpos]; } WordKey *pl_lookup(char* name) { for(int i=0;i<pl_dictionary_count;i++) { if(strlcmp(name, pl_dictionary[i].name, 12)==0) { return &pl_dictionary[i]; } } return NULL; } int pl_addword() { if(pl_dictionary_size==0){ pl_dictionary=(WordKey*)malloc(sizeof(WordKey)*12); pl_dictionary_size=12; return 0; } if(pl_dictionary_size<=pl_dictionary_count) { void* tmp=realloc(pl_dictionary, pl_dictionary_size+sizeof(WordKey)*DICTIONARYSTEP); if(tmp==NULL) { vputs("Out of memory!! Epic Fail!!"); return -1; } pl_dictionary=(WordKey*)tmp; pl_dictionary_size+=sizeof(WordKey)*DICTIONARYSTEP; } return pl_dictionary_count++; } void execute_word(char *word, WordType type) { if(type==Number){ pl_push(atoi(word)); }else{ if(word[1]==0) //check the quick builtins first { if(word[0]=='.'){ int tmp=pl_pop(); sprintf( word, "%i\n", tmp); vputs(word); return; }else if(word[0]==';') { //...? }else if(word[0]=='+'){ pl_push(pl_pop()+pl_pop()); }else if(word[0]=='/'){ pl_push(pl_pop()/pl_pop()); }else if(word[0]=='-'){ pl_push(pl_pop()-pl_pop()); }else if(word[0]=='!'){ pl_push(pl_pop()-pl_pop()); }else if(word[0]=='%'){ pl_push(pl_pop()%pl_pop()); }else if(word[0]=='*'){ pl_push(pl_pop()*pl_pop()); }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{ vputs("I don't know the word "); vputs(word); vputs("\n"); } } } 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; execute_word(word,type); 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++; } } } 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); 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; }