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:
Wed Sep 26 04:12:57 2012 +0000
Revision:
9:4211d638b2e9
Parent:
8:f356684767ef
Child:
16:370b9e559f92
PS/2 keyboard now receives scan codes at least

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 9:4211d638b2e9 191 }else if(word[0]=='['){
earlz 9:4211d638b2e9 192 //begin quotation
earlz 9:4211d638b2e9 193 push_opcode(Push);
earlz 9:4211d638b2e9 194 push_opcode_word(pl_blockpos+3);
earlz 9:4211d638b2e9 195 push_opcode(Branch);
earlz 9:4211d638b2e9 196 push_target(pl_blockpos);
earlz 9:4211d638b2e9 197 push_opcode_word(0);
earlz 9:4211d638b2e9 198 }else if(word[0] == ']'){
earlz 9:4211d638b2e9 199 //end quotation
earlz 9:4211d638b2e9 200 push_opcode(Ret);
earlz 9:4211d638b2e9 201 write_blockword(last_target->target, pl_blockpos);
earlz 9:4211d638b2e9 202 pop_target();
earlz 6:a4dff59ef214 203 }
earlz 6:a4dff59ef214 204 }else if(strlcmp("if", word, 3)==0){
earlz 7:2ac6752d47d2 205 push_opcode(BranchFalse);
earlz 8:f356684767ef 206 push_target(pl_blockpos);
earlz 8:f356684767ef 207 push_opcode_word(0);
earlz 7:2ac6752d47d2 208 }else if(strlcmp("else", word, 5)==0){
earlz 7:2ac6752d47d2 209 push_opcode(Branch);
earlz 8:f356684767ef 210 int tmp=pl_blockpos;
earlz 8:f356684767ef 211 push_opcode_word(0);
earlz 8:f356684767ef 212 write_blockword(last_target->target,pl_blockpos);
earlz 7:2ac6752d47d2 213 pop_target();
earlz 7:2ac6752d47d2 214 push_target(tmp); //have to do it after we pop it or we fall into an infinite loop!
earlz 7:2ac6752d47d2 215 }else if(strlcmp("end", word, 4)==0){
earlz 8:f356684767ef 216 write_blockword(last_target->target,(uint16_t)pl_blockpos);
earlz 7:2ac6752d47d2 217 pop_target();
earlz 9:4211d638b2e9 218 }else if(strlcmp("tif", word, 4)==0){
earlz 9:4211d638b2e9 219 /**
earlz 9:4211d638b2e9 220 swap value 2 behind stack to front
earlz 9:4211d638b2e9 221 call.true 1 from stack
earlz 9:4211d638b2e9 222 call.false top of stack
earlz 9:4211d638b2e9 223 _label:
earlz 9:4211d638b2e9 224 **/
earlz 9:4211d638b2e9 225 //alloca(10);
earlz 9:4211d638b2e9 226 push_opcode(Push);
earlz 9:4211d638b2e9 227 push_opcode_dword(3);
earlz 9:4211d638b2e9 228 push_opcode(Pick);
earlz 9:4211d638b2e9 229 push_opcode(BranchFalse);
earlz 9:4211d638b2e9 230 //push_opcode_word(pl_blockpos+
earlz 9:4211d638b2e9 231
earlz 6:a4dff59ef214 232 }else{
earlz 7:2ac6752d47d2 233 vputs("I don't know the word '");
earlz 6:a4dff59ef214 234 vputs(word);
earlz 7:2ac6752d47d2 235 vputs("'\n");
earlz 6:a4dff59ef214 236 }
earlz 6:a4dff59ef214 237 }
earlz 6:a4dff59ef214 238 return 0;
earlz 6:a4dff59ef214 239 }
earlz 6:a4dff59ef214 240
earlz 6:a4dff59ef214 241
earlz 6:a4dff59ef214 242
earlz 6:a4dff59ef214 243 void parse_line(char *line)
earlz 6:a4dff59ef214 244 {
earlz 6:a4dff59ef214 245 int len=strlen(line);
earlz 6:a4dff59ef214 246 char word[16];
earlz 6:a4dff59ef214 247 word[0]=0;
earlz 6:a4dff59ef214 248 int wordpos=0;
earlz 6:a4dff59ef214 249 WordType type=Unknown;
earlz 6:a4dff59ef214 250 for(int i=0;i<len;i++)
earlz 6:a4dff59ef214 251 {
earlz 6:a4dff59ef214 252 char c=line[i];
earlz 6:a4dff59ef214 253 if(is_whitespace(c) || c=='\\')
earlz 6:a4dff59ef214 254 {
earlz 6:a4dff59ef214 255 if(word[0]!=0)
earlz 6:a4dff59ef214 256 {
earlz 6:a4dff59ef214 257 word[wordpos]=0;
earlz 6:a4dff59ef214 258
earlz 6:a4dff59ef214 259 int tmp=compile_word(word,type);
earlz 6:a4dff59ef214 260 if(tmp==1)
earlz 6:a4dff59ef214 261 {
earlz 6:a4dff59ef214 262 execute_codeblock();
earlz 6:a4dff59ef214 263 new_codeblock(true);
earlz 6:a4dff59ef214 264 }
earlz 6:a4dff59ef214 265 word[0]=0;
earlz 6:a4dff59ef214 266 }
earlz 6:a4dff59ef214 267 wordpos=0;
earlz 6:a4dff59ef214 268 type=Unknown;
earlz 6:a4dff59ef214 269 if(c=='\\'){
earlz 6:a4dff59ef214 270 return; //rest is a comment
earlz 6:a4dff59ef214 271 }
earlz 6:a4dff59ef214 272 }else if(is_numeric(c)){
earlz 6:a4dff59ef214 273 if(type==Unknown){
earlz 6:a4dff59ef214 274 type=Number;
earlz 6:a4dff59ef214 275 }
earlz 6:a4dff59ef214 276 word[wordpos]=c;
earlz 6:a4dff59ef214 277 wordpos++;
earlz 6:a4dff59ef214 278 }else if(is_quote(c)){
earlz 9:4211d638b2e9 279 push_opcode(LoadStr);
earlz 9:4211d638b2e9 280 for(;i<len;i++)
earlz 9:4211d638b2e9 281 {
earlz 9:4211d638b2e9 282 //char c=line[
earlz 9:4211d638b2e9 283 }
earlz 6:a4dff59ef214 284 vputs("This isn't supported yet foo!");
earlz 6:a4dff59ef214 285 return;
earlz 6:a4dff59ef214 286 }else{
earlz 6:a4dff59ef214 287 if(type==Number){
earlz 6:a4dff59ef214 288 vputs("Syntax Error! Unexpected symbol in the middle of a number");
earlz 6:a4dff59ef214 289 return;
earlz 6:a4dff59ef214 290 }
earlz 6:a4dff59ef214 291 type=Word;
earlz 6:a4dff59ef214 292 word[wordpos]=c;
earlz 6:a4dff59ef214 293 wordpos++;
earlz 6:a4dff59ef214 294 }
earlz 6:a4dff59ef214 295 }
earlz 6:a4dff59ef214 296 }
earlz 6:a4dff59ef214 297
earlz 6:a4dff59ef214 298
earlz 6:a4dff59ef214 299 void tester()
earlz 6:a4dff59ef214 300 {
earlz 6:a4dff59ef214 301 printf("foo!");
earlz 6:a4dff59ef214 302 }
earlz 6:a4dff59ef214 303
earlz 6:a4dff59ef214 304 int pl_shell()
earlz 6:a4dff59ef214 305 {
earlz 6:a4dff59ef214 306 vputs(">>plEarlz -- A forth-ish shell<<\n");
earlz 6:a4dff59ef214 307 printheapstats();
earlz 6:a4dff59ef214 308 vputs("\n");
earlz 6:a4dff59ef214 309 char *line=(char*)malloc(MAXLINELENGTH);
earlz 9:4211d638b2e9 310 sprintf(line, "Stack Size: %i; Max Recursion Level %i; Loaded WORDs: %i", MAXSTACK, MAXTEMPSTACK, 0);
earlz 6:a4dff59ef214 311 vputs(line);
earlz 6:a4dff59ef214 312 sprintf(line, "Max line length: %i\n", MAXLINELENGTH);
earlz 6:a4dff59ef214 313 vputs(line);
earlz 6:a4dff59ef214 314 new_codeblock(false);
earlz 6:a4dff59ef214 315 char *tmp=(char*)malloc(32); //for constructing words/elements
earlz 6:a4dff59ef214 316 while(1)
earlz 6:a4dff59ef214 317 {
earlz 6:a4dff59ef214 318 vputs("cmd> ");
earlz 6:a4dff59ef214 319 vgetsl(line, MAXLINELENGTH);
earlz 6:a4dff59ef214 320 line[MAXLINELENGTH-1]=0;
earlz 6:a4dff59ef214 321 int len=strlen(line);
earlz 6:a4dff59ef214 322 line[len]='\n';
earlz 6:a4dff59ef214 323 line[len+1]=0;
earlz 6:a4dff59ef214 324 parse_line(line);
earlz 6:a4dff59ef214 325
earlz 6:a4dff59ef214 326 }
earlz 6:a4dff59ef214 327 free(line);
earlz 6:a4dff59ef214 328 free(tmp);
earlz 6:a4dff59ef214 329 return 0;
earlz 6:a4dff59ef214 330 }
earlz 6:a4dff59ef214 331
earlz 6:a4dff59ef214 332