contr is a library designed to allow a reactive programming style to be used in C for embedded applications. It was originally written to make writing a simple timer running on TI's MSP430 LaunchPad (to control a pump for my aeroponic garden) more fun.
Define indices into the contexts array for each unique reactive value.
enum reactives {
R_TIME = 0,
R_BUTTON
};
In the code where you want to use these values, get the stack pointer with GET_SP, and store it.
word *start;
GET_SP(start);
Call the r_{type}() function, passing start, NULL, the reactive value's index, and the initial value. The control flow of your program must call the r_{type}() functions before calling the corresponding r_call_{type}() functions for them to work correctly.
t = r_uint16_t(start, NULL, R_TIME, 0);
If you want to evaluate a block of code only when the reactive value changes, wrap it in a BLOCK. Make sure that any variables you want to stay updated are not on the stack. (e.g. static)
static uint16_t x;
BLOCK(a_block) {
t = r_uint16_t(start, a_block, R_TIME, 0);
x = computationally_expensive_function(t);
}
In your interrupt handler, call r_call_{type}() with the reactive value's index and the new value.
__attribute__((interrupt(TIMERA0_VECTOR)))
void timer_isr() {
static uint16_t timer_cnt = 0;
r_call_uint16_t(R_TIME, timer_cnt++);
}
Make sure there are enough contexts and stack storage for your program by defining the MAX_CONTEXTS and MAX_STACK_SPACE appropriately, by passing -DMAX_CONTEXTS=x and -DMAX_STACK_SPACE=y to gcc when compiling the library. If you define DEBUG, contr will warn you if you don't have enough stack space. See the Makefile for examples.
Now you're ready to use contr in your program!
Run make clean first.
- test:
make ARCH=X86 testormake ARCH=X86_64 test - test-msp430 (for MSP430 LaunchPad):
make ARCH=MSP430 test-msp430.elf - pump (for MSP430 LaunchPad):
make ARCH=MSP430 pump.elf - exp_board (for FRAM Experimenter's Board): `make ARCH=MSP430 exp_board.elf
The GET_SP and SET_SP functions need to be defined in assembly. Also, if the stack does not grow down (towards a lower address), more work will need to be done. I intend to add support for the AVR ATmega family of microprocessors.
The method of using continuations in C was inspired by Dan Piponi's (sigfpe) Continuations in C.