Skip to content

Instantly share code, notes, and snippets.

Created September 21, 2015 11:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/f2538963efcac6d3993b to your computer and use it in GitHub Desktop.
Save anonymous/f2538963efcac6d3993b to your computer and use it in GitHub Desktop.
SIMPL Interpreter to allow hardware exercse of most cpus in C
// 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