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