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
Diff: plEarlz.cpp
- Revision:
- 6:a4dff59ef214
- Parent:
- 5:367397a82ddc
- Child:
- 7:2ac6752d47d2
--- a/plEarlz.cpp Thu Sep 20 04:43:50 2012 +0000 +++ b/plEarlz.cpp Fri Sep 21 04:53:45 2012 +0000 @@ -1,255 +1,262 @@ -#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; -} - - +#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; +} + +