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

Committer:
earlz
Date:
Sat Sep 22 04:14:01 2012 +0000
Revision:
8:f356684767ef
Parent:
7:2ac6752d47d2
Child:
9:4211d638b2e9
IF statements now work, which makes loops trivial. Also added a few opcodes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
earlz 6:a4dff59ef214 1 #include "mbedconsole.h"
earlz 6:a4dff59ef214 2 #include "plEarlz.h"
earlz 6:a4dff59ef214 3 #include <stdarg.h>
earlz 6:a4dff59ef214 4 #include <stdint.h>
earlz 6:a4dff59ef214 5 //Basically a non-conforming take on Forth, btw.
earlz 6:a4dff59ef214 6
earlz 6:a4dff59ef214 7 inline int internal_captureline(void* pBuffer, char const* pFormatString, ...)
earlz 6:a4dff59ef214 8 {
earlz 6:a4dff59ef214 9 char* pStringEnd = (char*)pBuffer + strlen((char*)pBuffer);
earlz 6:a4dff59ef214 10 va_list valist;
earlz 6:a4dff59ef214 11
earlz 6:a4dff59ef214 12 va_start(valist, pFormatString);
earlz 6:a4dff59ef214 13
earlz 6:a4dff59ef214 14 return vsprintf(pStringEnd, pFormatString, valist);
earlz 6:a4dff59ef214 15 }
earlz 6:a4dff59ef214 16 void printheapstats()
earlz 6:a4dff59ef214 17 {
earlz 6:a4dff59ef214 18 char buffer[256];
earlz 6:a4dff59ef214 19 __heapstats(internal_captureline, buffer);
earlz 6:a4dff59ef214 20 vputs("Memory info: ");
earlz 6:a4dff59ef214 21 vputs(buffer);
earlz 6:a4dff59ef214 22 }
earlz 6:a4dff59ef214 23
earlz 6:a4dff59ef214 24
earlz 6:a4dff59ef214 25
earlz 6:a4dff59ef214 26
earlz 6:a4dff59ef214 27
earlz 8:f356684767ef 28 BranchTarget *last_target=NULL;
earlz 7:2ac6752d47d2 29
earlz 6:a4dff59ef214 30 ErrorType pl_error=None;
earlz 6:a4dff59ef214 31
earlz 6:a4dff59ef214 32
earlz 6:a4dff59ef214 33 enum WordType
earlz 6:a4dff59ef214 34 {
earlz 6:a4dff59ef214 35 Unknown,
earlz 6:a4dff59ef214 36 Number,
earlz 6:a4dff59ef214 37 Word,
earlz 6:a4dff59ef214 38 Quote
earlz 6:a4dff59ef214 39 };
earlz 6:a4dff59ef214 40
earlz 6:a4dff59ef214 41 uint8_t *pl_codeblock;
earlz 6:a4dff59ef214 42 int pl_blockpos;
earlz 6:a4dff59ef214 43 int pl_blocksize;
earlz 6:a4dff59ef214 44
earlz 7:2ac6752d47d2 45 uint8_t* push_opcode_byte(uint8_t val)
earlz 6:a4dff59ef214 46 {
earlz 6:a4dff59ef214 47 if(pl_blockpos>=pl_blocksize)
earlz 6:a4dff59ef214 48 {
earlz 6:a4dff59ef214 49 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
earlz 6:a4dff59ef214 50 if(tmp==NULL)
earlz 6:a4dff59ef214 51 {
earlz 6:a4dff59ef214 52 vputs("Out of memory!!");
earlz 6:a4dff59ef214 53 return;
earlz 6:a4dff59ef214 54 }
earlz 6:a4dff59ef214 55 pl_codeblock=(uint8_t*)tmp;
earlz 6:a4dff59ef214 56 pl_blocksize+=CODEBLOCKSTEP;
earlz 6:a4dff59ef214 57 }
earlz 6:a4dff59ef214 58 pl_codeblock[pl_blockpos]=val;
earlz 6:a4dff59ef214 59 pl_blockpos++;
earlz 7:2ac6752d47d2 60 return &pl_codeblock[pl_blockpos-1];
earlz 6:a4dff59ef214 61 }
earlz 7:2ac6752d47d2 62 Opcode* push_opcode(Opcode val)
earlz 6:a4dff59ef214 63 {
earlz 6:a4dff59ef214 64 if(pl_blockpos>=pl_blocksize)
earlz 6:a4dff59ef214 65 {
earlz 6:a4dff59ef214 66 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
earlz 6:a4dff59ef214 67 if(tmp==NULL)
earlz 6:a4dff59ef214 68 {
earlz 6:a4dff59ef214 69 vputs("Out of memory!!");
earlz 6:a4dff59ef214 70 return;
earlz 6:a4dff59ef214 71 }
earlz 6:a4dff59ef214 72 pl_codeblock=(uint8_t*)tmp;
earlz 6:a4dff59ef214 73 pl_blocksize+=CODEBLOCKSTEP;
earlz 6:a4dff59ef214 74 }
earlz 6:a4dff59ef214 75 pl_codeblock[pl_blockpos]=(uint8_t)val;
earlz 6:a4dff59ef214 76 pl_blockpos++;
earlz 7:2ac6752d47d2 77 return (Opcode*)&pl_codeblock[pl_blockpos-1];
earlz 6:a4dff59ef214 78 }
earlz 7:2ac6752d47d2 79 uint16_t* push_opcode_word(uint16_t val)
earlz 6:a4dff59ef214 80 {
earlz 6:a4dff59ef214 81 if(pl_blockpos>=pl_blocksize)
earlz 6:a4dff59ef214 82 {
earlz 6:a4dff59ef214 83 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
earlz 6:a4dff59ef214 84 if(tmp==NULL)
earlz 6:a4dff59ef214 85 {
earlz 6:a4dff59ef214 86 vputs("Out of memory!!");
earlz 6:a4dff59ef214 87 return;
earlz 6:a4dff59ef214 88 }
earlz 6:a4dff59ef214 89 pl_codeblock=(uint8_t*)tmp;
earlz 6:a4dff59ef214 90 pl_blocksize+=CODEBLOCKSTEP;
earlz 6:a4dff59ef214 91 }
earlz 6:a4dff59ef214 92 *(uint16_t*)&pl_codeblock[pl_blockpos]=val;
earlz 6:a4dff59ef214 93 pl_blockpos+=2;
earlz 7:2ac6752d47d2 94 return (uint16_t*)(&pl_codeblock[pl_blockpos-2]);
earlz 6:a4dff59ef214 95 }
earlz 7:2ac6752d47d2 96 uint32_t* push_opcode_dword(uint32_t val)
earlz 6:a4dff59ef214 97 {
earlz 6:a4dff59ef214 98 if(pl_blockpos>=pl_blocksize)
earlz 6:a4dff59ef214 99 {
earlz 6:a4dff59ef214 100 void* tmp=realloc(pl_codeblock, pl_blocksize+CODEBLOCKSTEP);
earlz 6:a4dff59ef214 101 if(tmp==NULL)
earlz 6:a4dff59ef214 102 {
earlz 6:a4dff59ef214 103 vputs("Out of memory!!");
earlz 6:a4dff59ef214 104 return;
earlz 6:a4dff59ef214 105 }
earlz 6:a4dff59ef214 106 pl_codeblock=(uint8_t*)tmp;
earlz 6:a4dff59ef214 107 pl_blocksize+=CODEBLOCKSTEP;
earlz 6:a4dff59ef214 108 }
earlz 6:a4dff59ef214 109 *(uint32_t*)&pl_codeblock[pl_blockpos]=val;
earlz 6:a4dff59ef214 110 pl_blockpos+=4;
earlz 7:2ac6752d47d2 111 return (uint32_t*)&pl_codeblock[pl_blockpos-4];
earlz 6:a4dff59ef214 112 }
earlz 6:a4dff59ef214 113 void new_codeblock(bool freeit)
earlz 6:a4dff59ef214 114 {
earlz 6:a4dff59ef214 115 if(freeit)
earlz 6:a4dff59ef214 116 {
earlz 6:a4dff59ef214 117 free(pl_codeblock);
earlz 6:a4dff59ef214 118 }
earlz 6:a4dff59ef214 119 pl_codeblock=(uint8_t*)malloc(CODEBLOCKSTEP);
earlz 6:a4dff59ef214 120 pl_blockpos=0;
earlz 6:a4dff59ef214 121 pl_blocksize=CODEBLOCKSTEP;
earlz 7:2ac6752d47d2 122 last_target=NULL;
earlz 6:a4dff59ef214 123 }
earlz 6:a4dff59ef214 124 int execute_codeblock()
earlz 6:a4dff59ef214 125 {
earlz 6:a4dff59ef214 126 return forth_execute(pl_codeblock, pl_blockpos);
earlz 6:a4dff59ef214 127 }
earlz 7:2ac6752d47d2 128
earlz 7:2ac6752d47d2 129
earlz 8:f356684767ef 130 void push_target(int address)
earlz 7:2ac6752d47d2 131 {
earlz 8:f356684767ef 132 BranchTarget* target=(BranchTarget*)malloc(sizeof(BranchTarget));
earlz 7:2ac6752d47d2 133 target->previous=last_target;
earlz 7:2ac6752d47d2 134 target->target=address;
earlz 7:2ac6752d47d2 135 last_target=target;
earlz 7:2ac6752d47d2 136 }
earlz 7:2ac6752d47d2 137 void pop_target()
earlz 7:2ac6752d47d2 138 {
earlz 7:2ac6752d47d2 139 if(last_target==NULL)
earlz 7:2ac6752d47d2 140 {
earlz 7:2ac6752d47d2 141 vputs("Unmatched control statement!\n");
earlz 7:2ac6752d47d2 142 return;
earlz 7:2ac6752d47d2 143 }
earlz 7:2ac6752d47d2 144 volatile void* tmp=last_target;
earlz 7:2ac6752d47d2 145 last_target=last_target->previous;
earlz 7:2ac6752d47d2 146 free((void*)tmp);
earlz 7:2ac6752d47d2 147 }
earlz 8:f356684767ef 148 inline void write_blockword(int pos,uint16_t val)
earlz 8:f356684767ef 149 {
earlz 8:f356684767ef 150 *(uint16_t*)&pl_codeblock[pos]=val;
earlz 8:f356684767ef 151 }
earlz 6:a4dff59ef214 152
earlz 6:a4dff59ef214 153 int compile_word(char *word, WordType type) //returns 0 for success, 1 for ending word found, -1 for error
earlz 6:a4dff59ef214 154 {
earlz 6:a4dff59ef214 155 if(type==Number){
earlz 6:a4dff59ef214 156 push_opcode(Push);
earlz 6:a4dff59ef214 157 push_opcode_dword(atoi(word));
earlz 6:a4dff59ef214 158 }else{
earlz 6:a4dff59ef214 159 if(word[1]==0) //check the quick builtins first
earlz 6:a4dff59ef214 160 {
earlz 6:a4dff59ef214 161 if(word[0]=='.'){
earlz 6:a4dff59ef214 162 push_opcode(CallInt);
earlz 6:a4dff59ef214 163 push_opcode_dword((uint32_t)&bi_print);
earlz 6:a4dff59ef214 164 }else if(word[0]==';')
earlz 6:a4dff59ef214 165 {
earlz 7:2ac6752d47d2 166 push_opcode(Ret);
earlz 6:a4dff59ef214 167 //execute!
earlz 6:a4dff59ef214 168 return 1;
earlz 6:a4dff59ef214 169 }else if(word[0]=='+'){
earlz 6:a4dff59ef214 170 push_opcode(Add);
earlz 6:a4dff59ef214 171 }else if(word[0]=='/'){
earlz 6:a4dff59ef214 172 push_opcode(Div);
earlz 6:a4dff59ef214 173 }else if(word[0]=='-'){
earlz 6:a4dff59ef214 174 push_opcode(Sub);
earlz 6:a4dff59ef214 175 }else if(word[0]=='!'){
earlz 6:a4dff59ef214 176 //pl_push(pl_pop()-pl_pop());
earlz 6:a4dff59ef214 177 }else if(word[0]=='%'){
earlz 6:a4dff59ef214 178 push_opcode(Mod);
earlz 6:a4dff59ef214 179 }else if(word[0]=='*'){
earlz 6:a4dff59ef214 180 push_opcode(Mul);
earlz 6:a4dff59ef214 181 }else if(word[0]=='!'){
earlz 7:2ac6752d47d2 182 //push_opcode(Store);
earlz 6:a4dff59ef214 183 }else if(word[0]=='?'){
earlz 6:a4dff59ef214 184 pl_push(*(int*)pl_pop());
earlz 6:a4dff59ef214 185 }else if(word[0]=='='){
earlz 6:a4dff59ef214 186 pl_push(pl_pop() == pl_pop());
earlz 6:a4dff59ef214 187 }else if(word[0]=='`'){
earlz 6:a4dff59ef214 188 pl_push(pl_pop()>0);
earlz 6:a4dff59ef214 189 }else if(word[0]=='$'){
earlz 6:a4dff59ef214 190 //print string (address on stack
earlz 6:a4dff59ef214 191 }
earlz 6:a4dff59ef214 192
earlz 6:a4dff59ef214 193 }else if(strlcmp("if", word, 3)==0){
earlz 7:2ac6752d47d2 194 push_opcode(BranchFalse);
earlz 8:f356684767ef 195 push_target(pl_blockpos);
earlz 8:f356684767ef 196 push_opcode_word(0);
earlz 7:2ac6752d47d2 197 }else if(strlcmp("else", word, 5)==0){
earlz 7:2ac6752d47d2 198 push_opcode(Branch);
earlz 8:f356684767ef 199 int tmp=pl_blockpos;
earlz 8:f356684767ef 200 push_opcode_word(0);
earlz 8:f356684767ef 201 write_blockword(last_target->target,pl_blockpos);
earlz 7:2ac6752d47d2 202 pop_target();
earlz 7:2ac6752d47d2 203 push_target(tmp); //have to do it after we pop it or we fall into an infinite loop!
earlz 7:2ac6752d47d2 204 }else if(strlcmp("end", word, 4)==0){
earlz 8:f356684767ef 205 write_blockword(last_target->target,(uint16_t)pl_blockpos);
earlz 7:2ac6752d47d2 206 pop_target();
earlz 6:a4dff59ef214 207 }else{
earlz 7:2ac6752d47d2 208 vputs("I don't know the word '");
earlz 6:a4dff59ef214 209 vputs(word);
earlz 7:2ac6752d47d2 210 vputs("'\n");
earlz 6:a4dff59ef214 211 }
earlz 6:a4dff59ef214 212 }
earlz 6:a4dff59ef214 213 return 0;
earlz 6:a4dff59ef214 214 }
earlz 6:a4dff59ef214 215
earlz 6:a4dff59ef214 216
earlz 6:a4dff59ef214 217
earlz 6:a4dff59ef214 218 void parse_line(char *line)
earlz 6:a4dff59ef214 219 {
earlz 6:a4dff59ef214 220 int len=strlen(line);
earlz 6:a4dff59ef214 221 char word[16];
earlz 6:a4dff59ef214 222 word[0]=0;
earlz 6:a4dff59ef214 223 int wordpos=0;
earlz 6:a4dff59ef214 224 WordType type=Unknown;
earlz 6:a4dff59ef214 225 for(int i=0;i<len;i++)
earlz 6:a4dff59ef214 226 {
earlz 6:a4dff59ef214 227 char c=line[i];
earlz 6:a4dff59ef214 228 if(is_whitespace(c) || c=='\\')
earlz 6:a4dff59ef214 229 {
earlz 6:a4dff59ef214 230 if(word[0]!=0)
earlz 6:a4dff59ef214 231 {
earlz 6:a4dff59ef214 232 word[wordpos]=0;
earlz 6:a4dff59ef214 233
earlz 6:a4dff59ef214 234 int tmp=compile_word(word,type);
earlz 6:a4dff59ef214 235 if(tmp==1)
earlz 6:a4dff59ef214 236 {
earlz 6:a4dff59ef214 237 execute_codeblock();
earlz 6:a4dff59ef214 238 new_codeblock(true);
earlz 6:a4dff59ef214 239 }
earlz 6:a4dff59ef214 240 word[0]=0;
earlz 6:a4dff59ef214 241 }
earlz 6:a4dff59ef214 242 wordpos=0;
earlz 6:a4dff59ef214 243 type=Unknown;
earlz 6:a4dff59ef214 244 if(c=='\\'){
earlz 6:a4dff59ef214 245 return; //rest is a comment
earlz 6:a4dff59ef214 246 }
earlz 6:a4dff59ef214 247 }else if(is_numeric(c)){
earlz 6:a4dff59ef214 248 if(type==Unknown){
earlz 6:a4dff59ef214 249 type=Number;
earlz 6:a4dff59ef214 250 }
earlz 6:a4dff59ef214 251 word[wordpos]=c;
earlz 6:a4dff59ef214 252 wordpos++;
earlz 6:a4dff59ef214 253 }else if(is_quote(c)){
earlz 6:a4dff59ef214 254 vputs("This isn't supported yet foo!");
earlz 6:a4dff59ef214 255 return;
earlz 6:a4dff59ef214 256 }else{
earlz 6:a4dff59ef214 257 if(type==Number){
earlz 6:a4dff59ef214 258 vputs("Syntax Error! Unexpected symbol in the middle of a number");
earlz 6:a4dff59ef214 259 return;
earlz 6:a4dff59ef214 260 }
earlz 6:a4dff59ef214 261 type=Word;
earlz 6:a4dff59ef214 262 word[wordpos]=c;
earlz 6:a4dff59ef214 263 wordpos++;
earlz 6:a4dff59ef214 264 }
earlz 6:a4dff59ef214 265 }
earlz 6:a4dff59ef214 266 }
earlz 6:a4dff59ef214 267
earlz 6:a4dff59ef214 268
earlz 6:a4dff59ef214 269 void tester()
earlz 6:a4dff59ef214 270 {
earlz 6:a4dff59ef214 271 printf("foo!");
earlz 6:a4dff59ef214 272 }
earlz 6:a4dff59ef214 273
earlz 6:a4dff59ef214 274 int pl_shell()
earlz 6:a4dff59ef214 275 {
earlz 6:a4dff59ef214 276 vputs(">>plEarlz -- A forth-ish shell<<\n");
earlz 6:a4dff59ef214 277 printheapstats();
earlz 6:a4dff59ef214 278 vputs("\n");
earlz 6:a4dff59ef214 279 char *line=(char*)malloc(MAXLINELENGTH);
earlz 6:a4dff59ef214 280 sprintf(line, "Stack Size: %i; Max Recursion Level %i; Loaded WORDs: %i", MAXSTACK, MAXCALLS, 0);
earlz 6:a4dff59ef214 281 vputs(line);
earlz 6:a4dff59ef214 282 sprintf(line, "Max line length: %i\n", MAXLINELENGTH);
earlz 6:a4dff59ef214 283 vputs(line);
earlz 6:a4dff59ef214 284 new_codeblock(false);
earlz 6:a4dff59ef214 285 char *tmp=(char*)malloc(32); //for constructing words/elements
earlz 6:a4dff59ef214 286 while(1)
earlz 6:a4dff59ef214 287 {
earlz 6:a4dff59ef214 288 vputs("cmd> ");
earlz 6:a4dff59ef214 289 vgetsl(line, MAXLINELENGTH);
earlz 6:a4dff59ef214 290 line[MAXLINELENGTH-1]=0;
earlz 6:a4dff59ef214 291 int len=strlen(line);
earlz 6:a4dff59ef214 292 line[len]='\n';
earlz 6:a4dff59ef214 293 line[len+1]=0;
earlz 6:a4dff59ef214 294 parse_line(line);
earlz 6:a4dff59ef214 295
earlz 6:a4dff59ef214 296 }
earlz 6:a4dff59ef214 297 free(line);
earlz 6:a4dff59ef214 298 free(tmp);
earlz 6:a4dff59ef214 299 return 0;
earlz 6:a4dff59ef214 300 }
earlz 6:a4dff59ef214 301
earlz 6:a4dff59ef214 302