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-21
Revision:
6:a4dff59ef214
Parent:
5:367397a82ddc
Child:
7:2ac6752d47d2

File content as of revision 6:a4dff59ef214:

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