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

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;
+}
+
+