Skip to content

Instantly share code, notes, and snippets.

Created March 2, 2016 18:09
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save anonymous/034dd41f108263d09803 to your computer and use it in GitHub Desktop.
Save anonymous/034dd41f108263d09803 to your computer and use it in GitHub Desktop.
A version of SIMPL to run on the MSP430G2553 Launchpad
// 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