Created
September 21, 2015 11:56
-
-
Save anonymous/f2538963efcac6d3993b to your computer and use it in GitHub Desktop.
SIMPL Interpreter to allow hardware exercse of most cpus in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SIMPL basic interpreter Framework | |
// Based on Txtzyme Interpreter for Arduino - by Ward Cunningham | |
// This version compiles to 2026 bytes using Arduino 1.70 | |
// Ken Boak 2013 - 2015 | |
// A simple interpreted utility that allows basic harware and arithmetic to be exercised from the serial terminal | |
// This version eliminates a lot of Arduino specific functions | |
// replacing serial functions with u_getchar and u_putchar | |
// printnum prints an unsigned integer | |
// Normal setup() and loop have been replaced with a main() and while(1) | |
//#include <avr/io.h> | |
#define F_CPU 16000000UL | |
#define BAUD 115200 | |
#include <util/setbaud.h> | |
unsigned int x = 0; // Thee gen purpose variables | |
unsigned int y = 0; | |
unsigned int z = 0; | |
int d = 6; // This is the output pin with the LED on the dev board | |
unsigned int num = 0; | |
unsigned int num_val = 0; | |
int j; | |
char num_buf[10]; | |
int decade = 0; | |
char digit = 0; | |
//void setup() | |
int main() | |
{ | |
// This replaces setup() | |
// Enable UART | |
uart_init(); | |
DDRD = DDRD | B11111100; // Sets pins 2 to 7 as outputs without changing the value of pins 0 & 1, which are RX & TX | |
//void loop() | |
while(1) | |
{ | |
char buf[64]; | |
txtRead(buf, 64); | |
txtEval(buf); | |
} | |
} | |
void txtRead (char *p, byte n) { | |
byte i = 0; | |
while (i < (n-1)) { | |
// while(!loop_until_bit_is_set(UCSR0A, RXC0)); /* Wait until data exists. */ | |
char ch = u_getchar(); | |
if (ch == '\r' || ch == '\n') break; | |
if (ch >= ' ' && ch <= '~') { | |
*p++ = ch; | |
i++; | |
} | |
} | |
*p = 0; | |
} | |
void txtEval (char *buf) { | |
unsigned int k = 0; | |
char *loop; | |
char ch; | |
while ((ch = *buf++)) { | |
switch (ch) { | |
case '0': | |
case '1': | |
case '2': | |
case '3': | |
case '4': | |
case '5': | |
case '6': | |
case '7': | |
case '8': | |
case '9': | |
x = ch - '0'; | |
while (*buf >= '0' && *buf <= '9') { | |
x = x*10 + (*buf++ - '0'); | |
} | |
break; | |
//----------------------------------------------------------------------------------------------------------------------------------------------- | |
// Memory Group | |
case ' ': | |
y = x; // push x down | |
break; | |
case '!': | |
y = x; // Store | |
break; | |
case '@': | |
x = y; // Fetch | |
break; | |
//----------------------------------------------------------------------------------------------------------------------------------------------- | |
// Maths Group - provides +,-,*,/ and % Functions operating on x and y leaving the result in x | |
case '+': | |
x = x+y; | |
break; | |
case '-': | |
x = x-y; | |
break; | |
case '*': | |
x = x*y; | |
break; | |
case '/': | |
x = x/y; | |
break; | |
case '%': | |
x = x%y; | |
break; | |
//----------------------------------------------------------------------------------------------------------------------------------------------- | |
// Logical Group - provides bitwise logical function between x and y | |
case '&': | |
x = x&y; // Logical AND | |
break; | |
case '|': | |
x = x|y; // Logical OR | |
break; | |
case '^': | |
x = x^y; // Logical XOR | |
break; | |
case '~': | |
x = !x; // Complement x | |
break; | |
//----------------------------------------------------------------------------------------------------------------------------------------------- | |
// Comparison Group - Provides Greater Than, Less Than and Equal to comparisons between x and y | |
case '<': | |
if(x<y){x=1;} // If x<y x= 1 - can be combined with jump j | |
else x=0; | |
break; | |
case '>': | |
if(x>y){x=1;} // If x>y x= 1 - can be combined with jump j | |
else x=0; | |
break; | |
case '=': | |
if(x=y){x=1;} // If x>y x= 1 - can be combined with jump j | |
else x=0; | |
break; | |
//----------------------------------------------------------------------------------------------------------------------------------------------- | |
case 'h': | |
PORTD |= B01000000; // Set bit 6 high | |
break; | |
case 'l': | |
PORTD &= B10111111; // Set bit 6 low | |
break; | |
case 'p': | |
printnum(x); | |
u_putchar(10); | |
u_putchar(13); | |
break; | |
case 'd': | |
d = x; | |
break; | |
case 'i': | |
// x = digitalRead(d); | |
break; | |
case 'o': | |
// digitalWrite(d, x%2); | |
break; | |
case 'm': | |
delay(x); | |
break; | |
case 'u': | |
delayMicroseconds(x); | |
break; | |
case '{': | |
k = x; | |
loop = buf; | |
while ((ch = *buf++) && ch != '}') { | |
} | |
case '}': | |
if (k) { | |
k--; | |
buf = loop; | |
} | |
break; | |
case 'k': | |
x = k; | |
break; | |
case '_': | |
while ((ch = *buf++) && ch != '_') { | |
u_putchar(ch); | |
} | |
u_putchar(13); | |
u_putchar(10); | |
break; | |
case 's': | |
x = analogRead(x); | |
break; | |
} | |
} | |
} | |
//-------------------------------------------------------------------------------------- | |
// UART Routines | |
//-------------------------------------------------------------------------------------- | |
void uart_init(void) | |
{ | |
UBRR0H = UBRRH_VALUE; | |
UBRR0L = UBRRL_VALUE; | |
#if USE_2X | |
UCSR0A |= _BV(U2X0); | |
#else | |
UCSR0A &= ~(_BV(U2X0)); | |
#endif | |
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */ | |
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */ | |
} | |
void u_putchar(char c) { | |
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */ | |
UDR0 = c; | |
} | |
char u_getchar(void) { | |
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */ | |
return UDR0; | |
} | |
void printnum(int num) | |
{ | |
// num is likely going to be a 16 bit iunsigned int - so we are handling up to 5 digits | |
// We need to test which decade it is in - and convert the leading digit to ascii - remembering to suppress leading zeroes | |
num_val = num; // make a copy of num for later | |
// Now Test magnitude and extract the digits | |
/* | |
z=num/10000; // 10,000's | |
num_buf[5]=z+48; | |
num = num - (10000*z); | |
z=num/1000; // 1000's | |
num_buf[4]=z+48; | |
num = num - (1000*z); | |
z=num/100; // 100's | |
num_buf[3]=z+48; | |
num = num - (100*z); | |
z=num/10; // 10's | |
num_buf[2]=z+48; | |
num = num - (10*z); | |
z=num; // Units | |
num_buf[1]=z+48; | |
*/ | |
// Extract the digits into the num_buff | |
decade = 10000; | |
for (j = 5; j>0; j--) | |
{ | |
z = num/decade; | |
num_buf[j]=z+48; | |
num = num - (decade*z); | |
decade = decade/10; | |
} | |
// Now print out the array - correcting to allow for leading zero suppression | |
if (num_val == 0) | |
{ | |
{num_buf[5] = 48;} | |
} | |
decade = 10000; // we need to know what decade we are in for leading zero suppression | |
j=5; | |
while(num_buf[j]!=0) | |
{ | |
if(num_buf[j] == 48 && (num_val <= decade)) {j--;} // suppress leading zeroes | |
else | |
{ | |
u_putchar(num_buf[j]); // send the number | |
num_buf[j]=0; // erase the array for next time | |
j--; | |
} | |
decade = decade/10; // update the decade | |
} | |
if(!num_val){u_putchar(48); } // separately handle the case when num == 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment