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-26
Revision:
9:4211d638b2e9
Parent:
8:f356684767ef
Child:
16:370b9e559f92

File content as of revision 9:4211d638b2e9:

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





BranchTarget *last_target=NULL;   

ErrorType pl_error=None;


enum WordType
{
    Unknown,
    Number,
    Word,
    Quote
};

uint8_t *pl_codeblock;
int pl_blockpos;
int pl_blocksize;

uint8_t* 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++;
    return &pl_codeblock[pl_blockpos-1];
}
Opcode* 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++;
    return (Opcode*)&pl_codeblock[pl_blockpos-1];
}
uint16_t* 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;
    return (uint16_t*)(&pl_codeblock[pl_blockpos-2]);
}
uint32_t* 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;
    return (uint32_t*)&pl_codeblock[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;
    last_target=NULL;
}
int execute_codeblock()
{
    return forth_execute(pl_codeblock, pl_blockpos);
}
 

void push_target(int address)
{
    BranchTarget* target=(BranchTarget*)malloc(sizeof(BranchTarget));
    target->previous=last_target;
    target->target=address;
    last_target=target;
}
void pop_target()
{
    if(last_target==NULL)
    {
        vputs("Unmatched control statement!\n");
        return;
    }
    volatile void* tmp=last_target;
    last_target=last_target->previous;
    free((void*)tmp);
}
inline void write_blockword(int pos,uint16_t val)
{
    *(uint16_t*)&pl_codeblock[pos]=val;
}

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]==';')
            {
                push_opcode(Ret);
                //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]=='!'){
                //push_opcode(Store);
            }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(word[0]=='['){
                //begin quotation
                push_opcode(Push);
                push_opcode_word(pl_blockpos+3);
                push_opcode(Branch);
                push_target(pl_blockpos);
                push_opcode_word(0);
            }else if(word[0] == ']'){
                //end quotation
                push_opcode(Ret);
                write_blockword(last_target->target, pl_blockpos);
                pop_target();
            }
        }else if(strlcmp("if", word, 3)==0){
            push_opcode(BranchFalse);
            push_target(pl_blockpos);
            push_opcode_word(0);
        }else if(strlcmp("else", word, 5)==0){
            push_opcode(Branch);
            int tmp=pl_blockpos;
            push_opcode_word(0); 
            write_blockword(last_target->target,pl_blockpos);
            pop_target(); 
            push_target(tmp); //have to do it after we pop it or we fall into an infinite loop!
        }else if(strlcmp("end", word, 4)==0){
            write_blockword(last_target->target,(uint16_t)pl_blockpos);
            pop_target();
        }else if(strlcmp("tif", word, 4)==0){
            /**
            swap value 2 behind stack to front
            call.true 1 from stack
            call.false top of stack
            _label:
            **/
            //alloca(10);
            push_opcode(Push);
            push_opcode_dword(3);
            push_opcode(Pick);
            push_opcode(BranchFalse);
            //push_opcode_word(pl_blockpos+
            
        }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)){
            push_opcode(LoadStr);
            for(;i<len;i++)
            {
                //char c=line[
            }
            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, MAXTEMPSTACK, 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;
}