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 03:00:55 2012 +0000
Revision:
7:2ac6752d47d2
Parent:
6:a4dff59ef214
Child:
8:f356684767ef
fuck pointers

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 7:2ac6752d47d2 28 volatile 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 7:2ac6752d47d2 130 void push_target(uint16_t* address)
earlz 7:2ac6752d47d2 131 {
earlz 7:2ac6752d47d2 132 volatile 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 6:a4dff59ef214 148
earlz 6:a4dff59ef214 149 int compile_word(char *word, WordType type) //returns 0 for success, 1 for ending word found, -1 for error
earlz 6:a4dff59ef214 150 {
earlz 6:a4dff59ef214 151 if(type==Number){
earlz 6:a4dff59ef214 152 push_opcode(Push);
earlz 6:a4dff59ef214 153 push_opcode_dword(atoi(word));
earlz 6:a4dff59ef214 154 }else{
earlz 6:a4dff59ef214 155 if(word[1]==0) //check the quick builtins first
earlz 6:a4dff59ef214 156 {
earlz 6:a4dff59ef214 157 if(word[0]=='.'){
earlz 6:a4dff59ef214 158 push_opcode(CallInt);
earlz 6:a4dff59ef214 159 push_opcode_dword((uint32_t)&bi_print);
earlz 6:a4dff59ef214 160 }else if(word[0]==';')
earlz 6:a4dff59ef214 161 {
earlz 7:2ac6752d47d2 162 push_opcode(Ret);
earlz 6:a4dff59ef214 163 //execute!
earlz 6:a4dff59ef214 164 return 1;
earlz 6:a4dff59ef214 165 }else if(word[0]=='+'){
earlz 6:a4dff59ef214 166 push_opcode(Add);
earlz 6:a4dff59ef214 167 }else if(word[0]=='/'){
earlz 6:a4dff59ef214 168 push_opcode(Div);
earlz 6:a4dff59ef214 169 }else if(word[0]=='-'){
earlz 6:a4dff59ef214 170 push_opcode(Sub);
earlz 6:a4dff59ef214 171 }else if(word[0]=='!'){
earlz 6:a4dff59ef214 172 //pl_push(pl_pop()-pl_pop());
earlz 6:a4dff59ef214 173 }else if(word[0]=='%'){
earlz 6:a4dff59ef214 174 push_opcode(Mod);
earlz 6:a4dff59ef214 175 }else if(word[0]=='*'){
earlz 6:a4dff59ef214 176 push_opcode(Mul);
earlz 6:a4dff59ef214 177 }else if(word[0]=='!'){
earlz 7:2ac6752d47d2 178 //push_opcode(Store);
earlz 6:a4dff59ef214 179 }else if(word[0]=='?'){
earlz 6:a4dff59ef214 180 pl_push(*(int*)pl_pop());
earlz 6:a4dff59ef214 181 }else if(word[0]=='='){
earlz 6:a4dff59ef214 182 pl_push(pl_pop() == pl_pop());
earlz 6:a4dff59ef214 183 }else if(word[0]=='`'){
earlz 6:a4dff59ef214 184 pl_push(pl_pop()>0);
earlz 6:a4dff59ef214 185 }else if(word[0]=='$'){
earlz 6:a4dff59ef214 186 //print string (address on stack
earlz 6:a4dff59ef214 187 }
earlz 6:a4dff59ef214 188
earlz 6:a4dff59ef214 189 }else if(strlcmp("if", word, 3)==0){
earlz 7:2ac6752d47d2 190 printf("if statement %x\r\n", pl_blockpos);
earlz 7:2ac6752d47d2 191 push_opcode(BranchFalse);
earlz 7:2ac6752d47d2 192 push_target(push_opcode_word(0));
earlz 7:2ac6752d47d2 193 }else if(strlcmp("else", word, 5)==0){
earlz 7:2ac6752d47d2 194 printf("else statement %x\r\n", pl_blockpos);
earlz 7:2ac6752d47d2 195 push_opcode(Branch);
earlz 7:2ac6752d47d2 196 uint16_t* tmp=push_opcode_word(0);
earlz 7:2ac6752d47d2 197 volatile uint16_t* tmp2=last_target->target;
earlz 7:2ac6752d47d2 198 *tmp2=pl_blockpos;
earlz 7:2ac6752d47d2 199 pop_target();
earlz 7:2ac6752d47d2 200 push_target(tmp); //have to do it after we pop it or we fall into an infinite loop!
earlz 7:2ac6752d47d2 201 }else if(strlcmp("end", word, 4)==0){
earlz 7:2ac6752d47d2 202 *(last_target->target)=pl_blockpos;
earlz 7:2ac6752d47d2 203 pop_target();
earlz 6:a4dff59ef214 204 }else{
earlz 7:2ac6752d47d2 205 vputs("I don't know the word '");
earlz 6:a4dff59ef214 206 vputs(word);
earlz 7:2ac6752d47d2 207 vputs("'\n");
earlz 6:a4dff59ef214 208 }
earlz 6:a4dff59ef214 209 }
earlz 6:a4dff59ef214 210 return 0;
earlz 6:a4dff59ef214 211 }
earlz 6:a4dff59ef214 212
earlz 6:a4dff59ef214 213
earlz 6:a4dff59ef214 214
earlz 6:a4dff59ef214 215 void parse_line(char *line)
earlz 6:a4dff59ef214 216 {
earlz 6:a4dff59ef214 217 int len=strlen(line);
earlz 6:a4dff59ef214 218 char word[16];
earlz 6:a4dff59ef214 219 word[0]=0;
earlz 6:a4dff59ef214 220 int wordpos=0;
earlz 6:a4dff59ef214 221 WordType type=Unknown;
earlz 6:a4dff59ef214 222 for(int i=0;i<len;i++)
earlz 6:a4dff59ef214 223 {
earlz 6:a4dff59ef214 224 char c=line[i];
earlz 6:a4dff59ef214 225 if(is_whitespace(c) || c=='\\')
earlz 6:a4dff59ef214 226 {
earlz 6:a4dff59ef214 227 if(word[0]!=0)
earlz 6:a4dff59ef214 228 {
earlz 6:a4dff59ef214 229 word[wordpos]=0;
earlz 6:a4dff59ef214 230
earlz 6:a4dff59ef214 231 int tmp=compile_word(word,type);
earlz 6:a4dff59ef214 232 if(tmp==1)
earlz 6:a4dff59ef214 233 {
earlz 6:a4dff59ef214 234 execute_codeblock();
earlz 6:a4dff59ef214 235 new_codeblock(true);
earlz 6:a4dff59ef214 236 }
earlz 6:a4dff59ef214 237 word[0]=0;
earlz 6:a4dff59ef214 238 }
earlz 6:a4dff59ef214 239 wordpos=0;
earlz 6:a4dff59ef214 240 type=Unknown;
earlz 6:a4dff59ef214 241 if(c=='\\'){
earlz 6:a4dff59ef214 242 return; //rest is a comment
earlz 6:a4dff59ef214 243 }
earlz 6:a4dff59ef214 244 }else if(is_numeric(c)){
earlz 6:a4dff59ef214 245 if(type==Unknown){
earlz 6:a4dff59ef214 246 type=Number;
earlz 6:a4dff59ef214 247 }
earlz 6:a4dff59ef214 248 word[wordpos]=c;
earlz 6:a4dff59ef214 249 wordpos++;
earlz 6:a4dff59ef214 250 }else if(is_quote(c)){
earlz 6:a4dff59ef214 251 vputs("This isn't supported yet foo!");
earlz 6:a4dff59ef214 252 return;
earlz 6:a4dff59ef214 253 }else{
earlz 6:a4dff59ef214 254 if(type==Number){
earlz 6:a4dff59ef214 255 vputs("Syntax Error! Unexpected symbol in the middle of a number");
earlz 6:a4dff59ef214 256 return;
earlz 6:a4dff59ef214 257 }
earlz 6:a4dff59ef214 258 type=Word;
earlz 6:a4dff59ef214 259 word[wordpos]=c;
earlz 6:a4dff59ef214 260 wordpos++;
earlz 6:a4dff59ef214 261 }
earlz 6:a4dff59ef214 262 }
earlz 6:a4dff59ef214 263 }
earlz 6:a4dff59ef214 264
earlz 6:a4dff59ef214 265
earlz 6:a4dff59ef214 266 void tester()
earlz 6:a4dff59ef214 267 {
earlz 6:a4dff59ef214 268 printf("foo!");
earlz 6:a4dff59ef214 269 }
earlz 6:a4dff59ef214 270
earlz 6:a4dff59ef214 271 int pl_shell()
earlz 6:a4dff59ef214 272 {
earlz 7:2ac6752d47d2 273 uint8_t* tmpf[20];
earlz 7:2ac6752d47d2 274 push_target((uint16_t*)&tmpf[2]);
earlz 7:2ac6752d47d2 275 *last_target->target=50;
earlz 7:2ac6752d47d2 276 pop_target();
earlz 7:2ac6752d47d2 277 push_target((uint16_t*)&tmpf[4]);
earlz 7:2ac6752d47d2 278 *last_target->target=200;
earlz 7:2ac6752d47d2 279 pop_target();
earlz 7:2ac6752d47d2 280
earlz 7:2ac6752d47d2 281 printf("foo: %i %i\r\n", (int)*(uint16_t*)&tmpf[2], (int)*(uint16_t*)&tmpf[4]);
earlz 6:a4dff59ef214 282 vputs(">>plEarlz -- A forth-ish shell<<\n");
earlz 6:a4dff59ef214 283 printheapstats();
earlz 6:a4dff59ef214 284 vputs("\n");
earlz 6:a4dff59ef214 285 char *line=(char*)malloc(MAXLINELENGTH);
earlz 6:a4dff59ef214 286 sprintf(line, "Stack Size: %i; Max Recursion Level %i; Loaded WORDs: %i", MAXSTACK, MAXCALLS, 0);
earlz 6:a4dff59ef214 287 vputs(line);
earlz 6:a4dff59ef214 288 sprintf(line, "Max line length: %i\n", MAXLINELENGTH);
earlz 6:a4dff59ef214 289 vputs(line);
earlz 6:a4dff59ef214 290 new_codeblock(false);
earlz 6:a4dff59ef214 291 char *tmp=(char*)malloc(32); //for constructing words/elements
earlz 6:a4dff59ef214 292 while(1)
earlz 6:a4dff59ef214 293 {
earlz 6:a4dff59ef214 294 vputs("cmd> ");
earlz 6:a4dff59ef214 295 vgetsl(line, MAXLINELENGTH);
earlz 6:a4dff59ef214 296 line[MAXLINELENGTH-1]=0;
earlz 6:a4dff59ef214 297 int len=strlen(line);
earlz 6:a4dff59ef214 298 line[len]='\n';
earlz 6:a4dff59ef214 299 line[len+1]=0;
earlz 6:a4dff59ef214 300 parse_line(line);
earlz 6:a4dff59ef214 301
earlz 6:a4dff59ef214 302 }
earlz 6:a4dff59ef214 303 free(line);
earlz 6:a4dff59ef214 304 free(tmp);
earlz 6:a4dff59ef214 305 return 0;
earlz 6:a4dff59ef214 306 }
earlz 6:a4dff59ef214 307
earlz 6:a4dff59ef214 308