Created
March 2, 2016 18:09
-
-
Save anonymous/034dd41f108263d09803 to your computer and use it in GitHub Desktop.
A version of SIMPL to run on the MSP430G2553 Launchpad
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 Interpreter for MSP430 Launchpad - inspired by an original idea by Ward Cunningham | |
// A minimal 868 byte Txtzyme for MSP430 Launchpad with MSP430G2533 | |
// Add in SIMPL framework - to allow construction and use of user defined words - increases to 1084 bytes | |
#define RXD BIT1 // Receive Data (RXD) at P1.1 | |
#define TXD BIT2 // Transmit Data (TXD) at P1.2 | |
#define RED 0x20 // Red LED is on Bit 6 | |
#define GREEN 0x01 // Green LED is on Bit 0 | |
#define bufRead(addr) (*(unsigned char *)(addr)) | |
#define bufWrite(addr, b) (*(unsigned char *)(addr) = (b)) | |
#define bit0 0x01 // 1 | |
#define bit1 0x02 // 2 | |
#define bit2 0x04 // 4 | |
#define bit3 0x08 // 8 | |
#define bit4 0x10 // 16 | |
#define bit5 0x20 // 32 | |
#define bit6 0x40 // 64 | |
#define bit7 0x80 // 128 | |
// This character array is used to hold the User's words | |
char array[5][48]; // Allocate a storage array in memory | |
/* | |
= { // Define a 26 x 48 array for the colon definitions | |
{"6d40{h1106ul1106u}"}, // Musical tones A - G | |
{"6d45{h986ul986u}"}, | |
{"6d51{h929ul929u}"}, | |
{"6d57{h825ul825u}"}, | |
{"6d64{h733ul733u}"}, | |
{"6d72{h690ul691u}"}, | |
{"6d81{h613ul613u}"}, | |
{"_Hello World, and welcome to SIMPL_"}, | |
{"5{ABC}"}, | |
{""}, | |
{""}, | |
{""}, | |
{"_This is a test message - about 48 characters_"} | |
}; | |
*/ | |
int a = 0; // integer variables a,b,c,d | |
int b = 0; | |
int c = 0; | |
int d = 6; // d is used to denote the digital port pin for I/O operations | |
// int d =13; // d is used to denote the digital port pin for I/O operations Pin 13 on Arduino | |
unsigned long x = 0; // Three gen purpose variables for stack & math operations | |
unsigned long y = 0; | |
unsigned int z = 0; | |
unsigned int ADC_value=0; | |
unsigned char in_byte; | |
int len = 32; // the max length of a User word | |
long old_millis=0; | |
long new_millis=0; | |
// long D_num = 0; | |
// long D_val = 0; | |
// long D_decade = 0; | |
char name; | |
char* parray; | |
char buf[64]; | |
char* addr; | |
unsigned int num = 0; | |
unsigned int num_val = 0; | |
int j; | |
char num_buf[11]; // long enough to hold a 32 bit long | |
int decade = 0; | |
char digit = 0; | |
// unsigned int x = 0; | |
// int d = 6; | |
/* | |
void uart_rx_isr(unsigned char c) { | |
uart_putc(c); | |
P1OUT ^= BIT0; // toggle P1.0 (red led) | |
} | |
void (*uart_rx_isr_ptr)(unsigned char c); | |
void uart_set_rx_isr_ptr(void (*isr_ptr)(unsigned char c)) | |
{ | |
uart_rx_isr_ptr = isr_ptr; | |
} | |
*/ | |
//------------------------------------------------------------------------------------ | |
// UART Routines | |
void uart_init(void) | |
{ | |
// uart_set_rx_isr_ptr(0L); | |
P1SEL = RXD + TXD; | |
P1SEL2 = RXD + TXD; | |
UCA0CTL1 |= UCSSEL_2; // SMCLK | |
UCA0BR0 = 104; // 1MHz 9600 | |
UCA0BR1 = 0; // 1MHz 9600 | |
UCA0MCTL = UCBRS0; // Modulation UCBRSx = 1 | |
UCA0CTL1 &= ~UCSWRST; // Initialize USCI state machine | |
// IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt | |
} | |
unsigned char uart_getc() | |
{ | |
while (!(IFG2&UCA0RXIFG)); // USCI_A0 RX buffer ready? | |
return UCA0RXBUF; | |
} | |
void uart_putc(unsigned char c) | |
{ | |
while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready? | |
UCA0TXBUF = c; // TX | |
} | |
void uart_puts(const char *str) // Output a string | |
{ | |
while(*str) uart_putc(*str++); | |
} | |
// Print a 16 bit int number | |
static void printlong(unsigned long num) | |
{ | |
if (num / (unsigned short)10 != 0) printlong(num / (unsigned short)10); | |
uart_putc((char)(num % (unsigned short)10) + '0'); | |
return; | |
} | |
// Print a CR-LF | |
void crlf(void) // send a crlf | |
{ | |
uart_putc(10); | |
uart_putc(13); | |
} | |
//------------------------------------------------------------------------------------- | |
// ADC Configuration | |
// Function containing ADC set-up | |
void ConfigureAdc(void) | |
{ | |
ADC10CTL1 = INCH_3 + ADC10DIV_3 ; // Channel 3, ADC10CLK/3 | |
ADC10CTL0 = SREF_0 + ADC10SHT_3 + ADC10ON + ADC10IE; // Vcc & Vss as reference, Sample and hold for 64 Clock cycles, ADC on, ADC interrupt enable | |
ADC10AE0 |= BIT3; // ADC input enable P1.3 | |
} | |
int ADC_Read(void) | |
{ | |
ADC10CTL0 |= ENC + ADC10SC; // Sampling and conversion start | |
// __bis_SR_register(CPUOFF + GIE); // Low Power Mode 0 with interrupts enabled | |
ADC_value = ADC10MEM; | |
return ADC_value; | |
} | |
//------------------------------------------------------------------------------------- | |
void delay_mS(int j){ | |
volatile unsigned long i; | |
while(j) | |
{ | |
i = 42; // Delay | |
do (i--); | |
while (i != 0); // busy waiting (bad) | |
j--; | |
} | |
} | |
/* | |
interrupt(USCIAB0RX_VECTOR) USCI0RX_ISR(void) | |
{ | |
if(uart_rx_isr_ptr != 0L) { | |
(uart_rx_isr_ptr)(UCA0RXBUF); | |
} | |
} | |
*/ | |
int main(void) | |
{ | |
WDTCTL = WDTPW + WDTHOLD; // Stop WDT | |
BCSCTL1 = CALBC1_1MHZ; // Set DCO | |
DCOCTL = CALDCO_1MHZ; | |
P1DIR = BIT0 + BIT6; // P1.0 and P1.6 are the red+green LEDs | |
P1OUT = BIT0 + BIT6; // All LEDs off | |
uart_init(); // Initialise the UART for 96000 baud | |
P1SEL |= BIT3; // ADC input pin P1.3 | |
ConfigureAdc(); | |
parray = &array[0][0]; // parray is the pointer to the first element | |
//------------------------------------------------------------------------------- | |
// pinMode(d,OUTPUT); | |
// register ISR called when data was received | |
// uart_set_rx_isr_ptr(uart_rx_isr); | |
// __bis_SR_register(GIE); | |
// uart_puts((char *)"MSP430 SIMPL\n\r"); // send banner message | |
while(1) | |
{ | |
txtRead(buf, 64); // This is the endless while loop which implements the interpreter - just 3 simple functions | |
txtChk(buf); // check if it is a : character for beginning a colon definition | |
txtEval(buf); | |
} | |
} // End of main | |
void txtRead (char *p, byte n) { | |
byte i = 0; | |
while (i < (n-1)) { | |
char ch = uart_getc(); | |
if (ch == '\r' || ch == '\n') break; | |
if (ch >= ' ' && ch <= '~') { | |
*p++ = ch; | |
i++; | |
} | |
} | |
*p = 0; | |
} | |
// --------------------------------------------------------------------------------------------------------- | |
void txtChk (char *buf) // Check if the text starts with a colon and if so store in temp[] | |
{ | |
if (*buf == ':') { | |
char ch; | |
int i =0; | |
while ((ch = *buf++)){ | |
if (ch == ':') { | |
uart_putc(*buf); // get the name from the first character | |
uart_putc(10); | |
uart_putc(13); | |
name = *buf ; | |
buf++; | |
} | |
bufWrite((parray + (len*(name-65) +i)),*buf); | |
i++; | |
} | |
x = 1; | |
} | |
} | |
void txtEval (char *buf) { | |
// unsigned int k = 0; | |
char *loop; | |
char *start; | |
char ch; | |
unsigned long k = 0; | |
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; | |
//------------------------------------------------------------------------------- | |
// User Words | |
case 'A': // Point the interpreter to the array containing the words | |
case 'B': | |
case 'C': | |
case 'D': | |
case 'E': | |
case 'F': | |
case 'G': | |
case 'H': | |
case 'I': | |
case 'J': | |
case 'K': | |
case 'L': | |
case 'M': | |
case 'N': | |
case 'O': | |
case 'P': | |
case 'Q': | |
case 'R': | |
case 'S': | |
case 'T': | |
case 'U': | |
case 'V': | |
case 'W': | |
case 'X': | |
case 'Y': | |
case 'Z': | |
// name = ch - 65; | |
addr = parray + (len*(ch-65)); | |
txtEval(addr); | |
break; | |
//--------------------------------------------------------------------------------- | |
// Primitive and User vocabulary defined in this section | |
// Timing & Printing Group | |
case 'p': | |
printlong(x); | |
break; | |
case 'q': // print integer with crlf | |
printlong(x); | |
crlf(); | |
break; | |
case 'b': | |
// printlong(millis()); | |
crlf(); | |
break; | |
case 'c': | |
// printlong(micros()); | |
crlf(); | |
break; | |
case 'd': | |
d = x; | |
break; | |
case '_': // Print the string encloseed between underscores _Hello_ | |
while ((ch = *buf++) && ch != '_') { | |
uart_putc(ch); | |
} | |
// uart_putc(10); | |
break; | |
//---------------------------------------------------------- | |
// Arithmetic Group | |
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; | |
case 'x': | |
x = x + 1; | |
break; | |
case 'y': | |
y = y + 1; | |
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; | |
// ---------------------------------------------------------------------- | |
// Memory Group | |
case '!': // store | |
y = x; | |
break; | |
case '@': // Fetch | |
x = y; | |
break; | |
/* | |
case 'r': // read a byte from RAM | |
bite = bufRead(x); // x = address | |
x = bite; | |
uart_putc(x); // print the character | |
break; | |
case 'q': // read a block of x bytes of RAM at address y | |
for (int i=0; i<x; i++) { | |
bite = bufRead(y+i); // read the array | |
uart_putc(bite); // print the character to the serial port | |
} | |
break; | |
case 'w': // write a byte to RAM address in y, data in x | |
bufWrite(y,x); | |
break; | |
*/ | |
//-------------------------------------------------------------------- | |
// Comparison Test and conditional Group | |
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 'j': // test if x = 1 and jump next instruction | |
if(x==1){*buf++;} | |
break; | |
//---------------------------------------------------------------------------------- | |
// Print out the current word list | |
case '?': // Print out all the RAM | |
parray = &array[0][0]; // reset parray to the pointer to the first element | |
for (int j = 0; j<26; j++) { | |
uart_putc(j+65); // print the caps word name | |
uart_putc(32); // space | |
for (int i=0; i<len; i++) { | |
in_byte = bufRead( parray + (j *len )+i); // read the array | |
uart_putc(in_byte); // print the character to the serial port | |
} | |
crlf(); | |
} | |
for(int i = 0; i <11; i++) // add some spaces to make it more legible on the page | |
{ | |
crlf(); | |
} | |
break; | |
//---------------------------------------------------------------------------------------------------- | |
// Conditional Code branch | |
case '[': // The start of a condition test | |
k = x; | |
start = buf; // remember the start position of the test | |
while ((ch = *buf++) && ch != ']') { // get the next character into ch and increment the buffer pointer *buf - evaluate the code | |
} | |
case ']': | |
if (x) { // if x is positive - go around again | |
buf = start; | |
} | |
break; | |
//-------------------------------------------------------------------------- | |
// Case Statement Selection | |
// Select some code from a list separated by commas | |
//5(0p,1p,2p,3p,4p,5p,6p) should select 5 and print it | |
case '(': | |
k = x; // copy x to use as the "phrase counter" | |
// decrement k to see whether to interpret or not | |
while (k) | |
{ | |
ch = *buf++; | |
if (ch == ',') | |
{ k--;} | |
} | |
break; | |
case ',': | |
k--; // | |
while (k<0) // k < 0 so skip the remaining entries in the list | |
{ | |
ch = *buf++; // skip the remaining characters | |
if (ch == ')') {break;} | |
} | |
break; | |
//----------------------------------------------------------------------------------------------------------------------------------------------- | |
// Analogue and Digital Input and Output Group - these add heavily to total - need to be converted to MSP430 | |
case 's': | |
x = ADC_Read(); // Adds 38 bytes | |
break; | |
/* | |
case 'a': | |
analogWrite(d,x); // adds 340 bytes | |
break; | |
case 'i': | |
x = digitalRead(d); // adds 100 bytes | |
break; | |
case 'o': | |
digitalWrite(d, x%2); // adds 18 bytes | |
break; | |
*/ | |
//------------------------------------------------------------------- | |
// Delays Group | |
case 'm': | |
delay_mS(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; | |
// ---------------------------------------------------------------------- | |
// Launchpad LED group | |
case 'w': | |
{ | |
P1OUT |= BIT0; | |
} | |
break; | |
case 'r': | |
{ | |
P1OUT &= ~BIT0; | |
} | |
break; | |
case 'h': | |
{ | |
P1OUT |= BIT6; | |
} | |
break; | |
case 'l': | |
{ | |
P1OUT &= ~BIT6; | |
} | |
break; | |
// ---------------------------------------------------------------------- | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment