Prelim code from xmas light project

This commit is contained in:
Ryan Voots 2016-04-23 21:46:07 -07:00
parent d8ba4cb814
commit 2abb66a248
22 changed files with 1367 additions and 0 deletions

36
teensy/Lualights.ino Normal file
View file

@ -0,0 +1,36 @@
/*
Blink
Turns on an LED on for one second, then off for one second, repeatedly.
This example code is in the public domain.
*/
#include "lua.hpp"
#include "wifi.h"
#include "http_lib.h"
#include "log.h"
#include "leds.h"
void setup() {
// initialize the digital pin as an output.
// Pin 13 has an LED connected on most Arduino boards:
//pinMode(13, OUTPUT);
LogOut.begin(9600);
delay(10000);
l_init();
setup_cc3000();
start_http();
setup_leds();
}
void loop() {
l_frame();
listen_http();
loop_leds();
//digitalWrite(13, HIGH); // set the LED on
//delay(100); // wait for a second
//digitalWrite(13, LOW); // set the LED off
//delay(100); // wait for a second
}

13
teensy/Makefile Normal file
View file

@ -0,0 +1,13 @@
BOARD_TAG = teensy31
ARDUINO_LIBS = Adafruit_CC3000 FastLED SPI
ARDUINO_DIR = /home/ryan/arduino/arduino-1.6.5
#AVR_TOOLS_DIR=/home/ryan/arduino/gcc-4.9/prefix/
CFLAGS += -Iinclude -Llib -llua -flto #-DSEND_NON_BLOCKING=1
CXXFLAGS += -Iinclude -Llib -llua -flto #-DSEND_NON_BLOCKING=1
# CPPFLAGS += -DSEND_NON_BLOCKING=1
# LDFLAGS += -flto
OTHER_OBJS += lib/liblua.a
include ../extern/Arduino-Makefile/Teensy.mk

15
teensy/README.md Normal file
View file

@ -0,0 +1,15 @@
Known issues
* CC3000 related lockups happen sometimes. Working on a solution but have not found it yet.
* HTTP server is rather slow since it sends 1 byte at a time. This is related to the above problem. sending data faster seems to cause more lockups.
* Lua evaluation is rather slow as it uses emulated floating point by default. Need to recompile with integer only math.
* No way to find out what the IP of the lights are. Need to add mDNS so that you can use "lights.local."
TODO
* mDNS support
* Better lua apis for setting large amounts of lights and calculating colors. (expose fastled apis).
* Lua http dispatching. Provide a way for lua code to create urls and respond to them. This might need an SD card for storage to do more than just an API layer.
* Maybe an http client for lua? That way you can get data from other sources?
* Add configuration options in the Makefile, to let you select what type of leds and how many you want to support
* Setup git submodules for the Arduino-mk makefile to make building easier
* Get LTO working to reduce binary size.

63
teensy/dispatch.h Normal file
View file

@ -0,0 +1,63 @@
#include <avr/pgmspace.h>
#define HANDLER(meth, num) void handle_ ## meth (Adafruit_CC3000_ClientRef &client) { \
uint8_t buffer[64]; \
memset(buffer, 0, 63); \
\
for (uint8_t p = 0; p < 63; p++) { \
buffer[p] = client.read(); \
\
if (buffer[p] == ' ' || buffer[p] == '?') { \
buffer[p] = 0; \
break; \
} \
} \
\
debug_log("GOT URL: "); \
debug_log((const char *) buffer); \
\
uint16_t length = sizeof(meth ## _LIST)/sizeof(meth ## _LIST[0]); \
\
debug_log("GET_LIST SIZE: "); \
debug_log(length); \
\
for (size_t i = 0; i < length; i++) { \
debug_log("Checking: "); \
debug_log(i); \
char path[64]; \
strncpy_P(path, meth ## _LIST[i].path, 63); \
debug_log("Path: "); \
debug_log(path); \
debug_logf((int) meth ## _LIST[i].path, HEX); \
debug_logf((int) root_path, HEX); \
\
if (!strncmp_P((const char *)buffer, meth ## _LIST[i].path, 63)) { \
skip_headers(client, num); \
(* meth ## _LIST[i].function)(client, num); \
client.println(F("\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n")); \
return; \
} \
} \
\
give_404(client, 0); \
}
#define PUSH(x) for(int i=0; i<3; i++) buffer[i] = buffer[i+1]; buffer[3]=x;
#define CHECK_BUF (buffer[0] == '\r' && buffer[1] == '\n' && buffer[2] == '\r' && buffer[3] == '\n')
METHOD(skip_headers) {
uint8_t buffer[4] = {0,0,0,0};
uint8_t c;
// Look for a \r\n\r\n pattern in the incoming data, that'll be the end of the headers
while(! CHECK_BUF) {
c = client.read();
PUSH(c);
}
}
HANDLER(GET, 0);
HANDLER(POST, 1);

6
teensy/docs.h Normal file
View file

@ -0,0 +1,6 @@
const char doc_gzip[] = {
0x1f, 0x8b, 0x08, 0x00, 0x8c, 0x1e, 0x7c, 0x54, 0x00, 0x03, 0x9d, 0x52, 0x5d, 0x4f, 0x83, 0x30, 0x14, 0x7d, 0xef, 0xaf, 0xb8, 0x8f, 0x1a, 0x58, 0xe6, 0xd4, 0xf9, 0xa0, 0x89, 0xc9, 0x82, 0xfb, 0xd2, 0x39, 0x8c, 0x23, 0xf1, 0xc1, 0x28, 0xa9, 0x50, 0x07, 0x19, 0x6b, 0x4d, 0x29, 0x33, 0xc6, 0xf9, 0xdf, 0xbd, 0x2d, 0x03, 0x61, 0x81, 0x68, 0xbc, 0x2f, 0xed, 0xed, 0x3d, 0xe7, 0xdc, 0xd3, 0xdb, 0x0e, 0x92, 0x04, 0xde, 0xa8, 0x8a, 0x52, 0x50, 0x74, 0xc5, 0xe0, 0xce, 0x5d, 0x78, 0x40, 0x53, 0x78, 0x15, 0x72, 0x0d, 0x8c, 0x07, 0x22, 0x8c, 0xf9, 0x12, 0x28, 0x0f, 0x41, 0x32, 0x95, 0x49, 0xae, 0x6b, 0xd7, 0x0b, 0x77, 0x4e, 0xc8, 0x60, 0x43, 0xe3, 0x84, 0xbe, 0x24, 0xc8, 0xd1, 0xf4, 0x73, 0xd2, 0x85, 0x0e, 0x78, 0x51, 0x9c, 0xc2, 0x95, 0x08, 0xb2, 0x35, 0xe3, 0x0a, 0x0e, 0xc6, 0x43, 0xef, 0x90, 0x74, 0x53, 0xa6, 0x14, 0xaa, 0xa4, 0xdd, 0x20, 0x93, 0x12, 0xcf, 0xbb, 0x81, 0x48, 0x84, 0x44, 0xb4, 0x93, 0xe7, 0x90, 0xe7, 0x1a, 0x6d, 0x1b, 0x03, 0x87, 0xf0, 0x28, 0x6d, 0x58, 0xda, 0xf0, 0xf2, 0xd4, 0xc0, 0x0e, 0xa9, 0x5c, 0x21, 0x79, 0x16, 0x2f, 0x23, 0x05, 0x2a, 0x92, 0x2c, 0x8d, 0x44, 0x12, 0xc2, 0x51, 0xa7, 0x77, 0x74, 0x7c, 0x5a, 0x57, 0xd1, 0xd0, 0x26, 0x09, 0x15, 0xaf, 0x19, 0x4a, 0x2c, 0x58, 0x20, 0x78, 0x88, 0x37, 0x17, 0x90, 0x2a, 0xfa, 0x01, 0x82, 0xa3, 0xca, 0x59, 0xbf, 0x7f, 0xd2, 0xaf, 0xcb, 0x68, 0xb8, 0x96, 0x51, 0x54, 0x65, 0x69, 0xd1, 0xbf, 0x30, 0x9f, 0x18, 0x1f, 0x92, 0x51, 0x33, 0x29, 0x73, 0xe5, 0x9f, 0xc6, 0x39, 0x63, 0xd7, 0xae, 0x60, 0x98, 0x74, 0x07, 0xac, 0x4b, 0xeb, 0xa5, 0x8a, 0xcc, 0xf3, 0x47, 0xb3, 0x3c, 0x11, 0xb2, 0xd0, 0x2b, 0x4e, 0x9a, 0xf1, 0x0c, 0x1f, 0xc7, 0xcf, 0xab, 0x9f, 0x0f, 0x83, 0xa9, 0x37, 0x9d, 0x8f, 0x6d, 0x98, 0x4d, 0xc7, 0x13, 0xcf, 0x77, 0x26, 0x43, 0xe7, 0xa6, 0x48, 0xdc, 0x79, 0xb1, 0xf3, 0xa6, 0xb7, 0x43, 0x1b, 0x46, 0xee, 0xbd, 0x33, 0xf4, 0xdd, 0xd1, 0xa8, 0xdc, 0xce, 0xbf, 0xf2, 0x2e, 0x17, 0x84, 0x40, 0x25, 0xb8, 0x00, 0x73, 0xcf, 0x3f, 0xc7, 0x5a, 0xa8, 0x58, 0x70, 0xd4, 0xb0, 0x3a, 0x8d, 0x61, 0xb5, 0x11, 0x5b, 0xf0, 0x9a, 0x82, 0x6a, 0x9b, 0x66, 0xd2, 0xb6, 0x4d, 0xad, 0x05, 0xaf, 0x29, 0xc4, 0xaa, 0x9a, 0xc9, 0xfd, 0x36, 0x18, 0xc0, 0xda, 0xee, 0xe6, 0x56, 0xed, 0x10, 0x27, 0x52, 0x72, 0x6a, 0x14, 0x8b, 0x6c, 0xe1, 0x9d, 0xc6, 0xfa, 0x87, 0xa1, 0xaf, 0xf2, 0xf8, 0x12, 0x13, 0xf3, 0x37, 0xfc, 0x20, 0x62, 0xc1, 0xaa, 0x57, 0xd6, 0x7e, 0x0a, 0xa8, 0x55, 0x21, 0x54, 0x2b, 0xe6, 0x8b, 0xec, 0x39, 0x6e, 0x1d, 0x99, 0xd5, 0x54, 0xd8, 0x9b, 0xf7, 0x9e, 0x63, 0x80, 0xe7, 0xb2, 0xa4, 0x7b, 0x89, 0x4c, 0xb5, 0x0e, 0xee, 0xb7, 0xd8, 0xb6, 0x3f, 0xfa, 0x3f, 0xc2, 0x22, 0xe4, 0x1b, 0x12, 0xe3, 0x7d, 0x55, 0x93, 0x04, 0x00, 0x00, };
const char inter_head[] = {
0x3c, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x4c, 0x75, 0x61, 0x20, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x20, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x6d, 0x69, 0x6e, 0x67, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3a, 0x20, 0x31, 0x30, 0x30, 0x25, 0x3b, 0x22, 0x20, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3d, 0x31, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x72, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x25, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x6e, 0x6f, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x75, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x79, 0x65, 0x74, 0x20, 0x2d, 0x2d, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x74, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x20, 0x72, 0x6f, 0x77, 0x73, 0x3d, 0x22, 0x34, 0x30, 0x22, 0x20, 0x63, 0x6f, 0x6c, 0x73, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x22, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x72, 0x67, 0x6d, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x70, 0x72, 0x67, 0x6d, 0x22, 0x3e, 0x0a, 00};
const char inter_foot[] = {
0x3c, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61, 0x3e, 0x0a, 0x3c, 0x62, 0x72, 0x20, 0x2f, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x22, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x66, 0x6f, 0x72, 0x6d, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, 0x64, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x35, 0x30, 0x25, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x69, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x73, 0x72, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x31, 0x39, 0x32, 0x2e, 0x31, 0x36, 0x38, 0x2e, 0x31, 0x2e, 0x32, 0x31, 0x35, 0x2f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x22, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x3d, 0x22, 0x31, 0x30, 0x30, 0x25, 0x22, 0x20, 0x2f, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x3c, 0x2f, 0x62, 0x6f, 0x64, 0x79, 0x3e, 0x0a, 0x3c, 0x2f, 0x68, 0x74, 0x6d, 0x6c, 0x3e, 0x0a, 00};

23
teensy/docs.txt Normal file
View file

@ -0,0 +1,23 @@
All paths take POST as form encoding and return as JSON
Available Paths:
/ - This Document (GET)
/settings/current/color - Current color (GET, POST) [r, g, b]
/settings/current/dark - Light threshold 0-1024 (GET, POST) [dark]
/settings/current/time - Seconds to stay on 0-65535 (GET, POST) [time]
/status/dark - Current light reading (GET) [dark]
/status/time - Current time (GET) [time]
/status/state - Current state [state]
States:
enum e_state {WAITING, LIGHT_CHECK, LIGHT_ON, LIGHT_TIME, FORCE_OFF, FORCE_ON} state;
no dark motion
+----------------------+ +-------------------------+
v | v |
+---------+ motion +--------------+ dark +----------+ no motion +------------+
| waiting | ---------> | light_check1 | ------> | light_on | -----------> | light_time |
+---------+ +--------------+ +----------+ +------------+
^ timeout |
+-------------------------------------------------------------------------+

13
teensy/gen_docs.sh Executable file
View file

@ -0,0 +1,13 @@
#!/bin/bash
echo const char doc_gzip[] = {
cat docs.txt | gzip -c | hexdump -ve '1/1 "0x%.2x, "'
echo }\;
echo const char inter_head[] = {
cat int_head.html | hexdump -ve '1/1 "0x%.2x, "'
echo 00}\;
echo const char inter_foot[] = {
cat int_foot.html | hexdump -ve '1/1 "0x%.2x, "'
echo 00}\;

170
teensy/handlers.h Normal file
View file

@ -0,0 +1,170 @@
#include "docs.h"
#include "log.h"
#include "lua.hpp"
const int GET = 0;
const int POST = 1;
#define METHOD(x) void x (Adafruit_CC3000_ClientRef &client, int method)
METHOD(give_200) {
client.fastrprint("HTTP/1.0 200 OK\r\n"
"Server: MiniC HTTPD 0.1\r\n"
"\r\n");
}
METHOD(give_400) {
client.fastrprint("HTTP/1.0 400 Bad Request\r\n"
"Server: MiniC HTTPD 0.1\r\n"
"\r\n");
}
METHOD(give_404) {
client.fastrprint("HTTP/1.0 404 Not Found\r\n"
"Server: MiniC HTTPD 0.1\r\n"
"\r\n");
client.fastrprint("Not found\r\n");
}
METHOD(give_200_gzip) {
client.fastrprint("HTTP/1.0 200 OK\r\n"
"Server: MiniC HTTPD 0.1\r\n"
"Content-Encoding: gzip\r\n"
"\r\n");
}
// Helpers
int read_name(Adafruit_CC3000_ClientRef &client, char *str) {
uint8_t i = 0,c = 0;
for (i=0; i<16 && c != '='; i++) {
c = client.read();
str[i] = c;
}
str[i-1] = 0; // end the string
return i;
}
int read_value(Adafruit_CC3000_ClientRef &client, char *str) {
uint8_t i = 0,c = 0;
for (i=0; i<16 && c != '&' && client.available(); i++) {
c = client.read();
str[i] = c;
}
if (str[i-1] == '&')
str[i-1] = 0;
return i;
}
// METHODS
METHOD(root) {
give_200_gzip(client, method);
for (uint16_t i = 0; i < sizeof(doc_gzip); i++)
client.write(pgm_read_byte(&doc_gzip[i]));
}
/* Converts a hex character to its integer value */
char from_hex(char ch) {
return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}
METHOD(interface) {
if (method == GET) {
give_200(client, method);
for (uint16_t i = 0; i < sizeof(inter_head); i++)
client.write(pgm_read_byte(&inter_head[i]));
for (uint16_t i = 0; i < sizeof(l_prog_buff) && l_prog_buff[i]; i++)
client.write(pgm_read_byte(&l_prog_buff[i]));
for (uint16_t i = 0; i < sizeof(inter_foot); i++)
client.write(pgm_read_byte(&inter_foot[i]));
} else {
if (client.available()) {
char name[16];
read_name(client, name);
if (!strncmp(name, "prgm", 16)) {
int i = 0;
char c;
memset(l_prog_buff, 0, sizeof(l_prog_buff));
for (i = 0; i < sizeof(l_prog_buff) && client.available(); i++) {
c = client.read();
if (c != '+' && c != '%') { // non-encoded char
l_prog_buff[i] = c;
} else if (c == '+') { // url encoded space
l_prog_buff[i] = ' ';
} else if (c == '%') { // % encoded string
char a, b;
a = client.read();
b = client.read();
c = from_hex(a) << 4 | from_hex(b);
l_prog_buff[i] = c;
}
}
output_log("\n");
output_log("Program loaded, compiling...\n");
l_stop();
l_start(l_prog_buff);
}
}
interface(client, GET); // give back the same GET output that we had before
}
}
METHOD(output) {
give_200(client, method);
char *p = log_curpos+1;
if (p - log_ringbuffer >= LOG_RINGSIZE)
p = log_ringbuffer;
client.fastrprint("<html><head><meta http-equiv=\"refresh\" content=\"5\"><body><pre>");
while(p != log_curpos) {
if (*p)
client.write(*p);
p++;
if (p - log_ringbuffer >= LOG_RINGSIZE)
p = log_ringbuffer;
}
client.fastrprint("</pre></body></html>");
}
// Setup the path resolver
struct method_resolve {
const prog_char *path;
void (*function)(Adafruit_CC3000_ClientRef&, int method);
};
#define FPATH(x) const prog_char x [] PROGMEM
#define ROUTE(m, p) {(const prog_char *) &p [0], m}
FPATH(root_path) = "/";
FPATH(output_path) = "/output";
FPATH(interface_path) = "/interface";
method_resolve GET_LIST[] = {
ROUTE(root, root_path),
ROUTE(output, output_path),
ROUTE(interface, interface_path),
};
method_resolve POST_LIST[] = {
ROUTE(root, root_path),
ROUTE(interface, interface_path),
};

47
teensy/http_lib.cpp Normal file
View file

@ -0,0 +1,47 @@
#include "log.h"
#include "http_lib.h"
#include "handlers.h"
#include "dispatch.h"
#include <Adafruit_CC3000.h>
Adafruit_CC3000_Server httpServer(80);
void start_http() {
httpServer.begin();
}
void read_method(Adafruit_CC3000_ClientRef &client) {
uint8_t method[9];
for (uint8_t i = 0; i < 8; i++) {
method[i] = client.read();
if (method[i] == ' ') {
method[i] = 0;
break;
}
}
if (!strncmp((const char *) method, "GET", 8)) {
handle_GET(client);
} else if (!strncmp((const char *) method, "POST", 8)) {
handle_POST(client);
} else {
// return a 400 to anything else.
client.fastrprint("HTTP/1.0 400 Bad Request\r\n"
"Server: MiniC HTTPD 0.1\r\n"
"\r\n"
"The fuck is wrong with you trying other methods?\r\n");
}
}
void listen_http() {
Adafruit_CC3000_ClientRef client = httpServer.available();
if (client) {
debug_log("GOT REQUEST, READING METHOD");
read_method(client);
client.close();
}
client.close();
}

10
teensy/http_lib.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef __LUALIGHTS_HTTP_LIB_H
#define __LUALIGHTS_HTTP_LIB_H
#include <Adafruit_CC3000.h>
extern Adafruit_CC3000_Server httpServer;
void start_http();
void listen_http();
#endif

12
teensy/int_foot.html Normal file
View file

@ -0,0 +1,12 @@
</textarea>
<br />
<input type="submit" value="Compile Program"/>
</form>
</td>
<td width="50%">
<iframe src="http://192.168.1.215/output" height="100%" width="100%" />
</td>
</tr>
</table>
</body>
</html>

11
teensy/int_head.html Normal file
View file

@ -0,0 +1,11 @@
<html>
<head>
<title>Lua Lights Programming Interface</title>
</head>
<body>
<table style="width: 100%;" border=1>
<tr>
<td width="50%" height="100%">
<!-- no place to put this yet -->
<form action="/interface" method="post">
<textarea rows="40" cols="100" name="prgm" id="prgm">

21
teensy/leds.cpp Normal file
View file

@ -0,0 +1,21 @@
#include "leds.h"
#include <FastLED.h>
CRGB led_data[MAX_NUM_LEDS];
// For led chips like Neopixels, which have a data line, ground, and power, you just
// need to define DATA_PIN. For led chipsets that are SPI based (four wires - data, clock,
// ground, and power), like the LPD8806 define both DATA_PIN and CLOCK_PIN
#define DATA_PIN 6
#define CLOCK_PIN 7
void setup_leds() {
FastLED.addLeds<WS2801, DATA_PIN, CLOCK_PIN, RGB>(led_data, MAX_NUM_LEDS);
};
void loop_leds() {
// for(int i = 0; i < 10; i++)
// led_data[i] = CRGB::White;
FastLED.show();
};

13
teensy/leds.h Normal file
View file

@ -0,0 +1,13 @@
#ifndef __LUALIGHTS_LEDS_H
#define __LUALIGHTS_LEDS_H
#include <FastLED.h>
#define MAX_NUM_LEDS 500
extern CRGB led_data[];
void setup_leds();
void loop_leds();
#endif

30
teensy/log.h Normal file
View file

@ -0,0 +1,30 @@
#ifndef __LUALIGHTS_LOG_H
#define __LUALIGHTS_LOG_H
// This line defines a "Uart" object to access the serial port
// HardwareSerial CommOut = HardwareSerial();
// usb_serial_class LogOut = Serial;
#define LogOut Serial
#define LOG_RINGSIZE 4096
extern char log_ringbuffer[LOG_RINGSIZE + 1]; // ring buffer for the output log
extern char *log_curpos;
#define debug_log(x) _debug_log(__BASE_FILE__, __FUNCTION__, __LINE__, x)
#define debug_logf(x, f) _debug_log(__BASE_FILE__, __FUNCTION__, __LINE__, x, f)
#define output_log(x) _output_log(__BASE_FILE__, __FUNCTION__, __LINE__, x)
#define output_logf(x, f) _output_log(__BASE_FILE__, __FUNCTION__, __LINE__, x, f)
// debug_log only logs to the Serial port, output_log will output to the ring buffer available to the webserver
void _debug_log(const char *file, const char* function, const int line, const char *message);
void _debug_log(const char *file, const char* function, const int line, int message);
void _debug_log(const char *file, const char* function, const int line, unsigned int message);
void _debug_log(const char *file, const char* function, const int line, char message);
void _debug_log(const char *file, const char* function, const int line, int message, int format);
// These need to also output to the ring buffer, right now that isn't so important
void _output_log(const char *file, const char* function, const int line, const char *message);
void _output_log(const char *file, const char* function, const int line, int message);
void _output_log(const char *file, const char* function, const int line, unsigned int message);
void _output_log(const char *file, const char* function, const int line, char message);
void _output_log(const char *file, const char* function, const int line, int message, int format);
#endif

105
teensy/logs.cpp Normal file
View file

@ -0,0 +1,105 @@
#include <Arduino.h>
#include "log.h"
char log_ringbuffer[LOG_RINGSIZE + 1];
char *log_curpos = log_ringbuffer;
void __debug_header(const char *file, const char *function, const int line) {
LogOut.print(file);
LogOut.print("<");
LogOut.print(function);
LogOut.print(">:");
LogOut.print(line);
LogOut.print(" ");
}
// debug_log only logs to the Serial port, output_log will output to the ring buffer available to the webserver
void _debug_log(const char *file, const char* function, const int line, const char *message) {
__debug_header(file, function, line);
LogOut.println(message);
}
void _debug_log(const char *file, const char* function, const int line, int message) {
__debug_header(file, function, line);
LogOut.println(message);
}
void _debug_log(const char *file, const char* function, const int line, unsigned int message) {
__debug_header(file, function, line);
LogOut.println(message);
}
void _debug_log(const char *file, const char* function, const int line, char message) {
__debug_header(file, function, line);
LogOut.println(message);
}
void _debug_log(const char *file, const char* function, const int line, int message, int format) {
__debug_header(file, function, line);
LogOut.println(message, format);
}
void _write_ring(const char *buff) {
size_t len = strlen(buff);
size_t p = log_curpos - log_ringbuffer;
if (LOG_RINGSIZE - p > len + 1) { // We've got enough space to just write it directly
memcpy(log_curpos, buff, len);
log_curpos += len;
} else { // Not enough space, we need to copy just enough and the go to the start of the buffer
size_t left = LOG_RINGSIZE - p;
memcpy(log_curpos, buff, left); // copy just the first part to the end of the buffer
memcpy(log_ringbuffer, buff + left, len - left); // copy the rest to the start of the buffer
log_curpos = log_ringbuffer + (len - left);
}
*log_curpos = 0; // set the current place to a nul, we gives us a good marker for the end
}
// These need to also output to the ring buffer, right now that isn't so important
void _output_log(const char *file, const char* function, const int line, const char *message) {
_debug_log(file, function, line, message); // Also put output to the serial connection
_write_ring(message);
}
void _output_log(const char *file, const char* function, const int line, int message) {
_debug_log(file, function, line, message); // Also put output to the serial connection
char buff[16];
sprintf(buff, "%d", message);
_write_ring(buff);
}
void _output_log(const char *file, const char* function, const int line, unsigned int message) {
_debug_log(file, function, line, message); // Also put output to the serial connection
char buff[16];
sprintf(buff, "%u", message);
_write_ring(buff);
}
void _output_log(const char *file, const char* function, const int line, char message) {
_debug_log(file, function, line, message); // Also put output to the serial connection
char buff[2];
buff[0] = message;
buff[1] = 0;
_write_ring(buff);
}
void _output_log(const char *file, const char* function, const int line, int message, int format) {
_debug_log(file, function, line, message); // Also put output to the serial connection
char buff[16];
switch(format) {
case BIN:
sprintf(buff, "%X", message); // I don't care so much about binary, quick HACK
break;
case OCT:
sprintf(buff, "%o", message);
break;
case DEC:
sprintf(buff, "%d", message);
break;
case HEX:
sprintf(buff, "%X", message);
break;
}
_write_ring(buff);
}

342
teensy/lua-alloc.c Normal file
View file

@ -0,0 +1,342 @@
/*
* Copyright (c) 2012, 2013 ARM Ltd
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the company may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Implementation of <<malloc>> <<free>> <<calloc>> <<realloc>>, optional
* as to be reenterable.
*
* Interface documentation refer to malloc.c.
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "lua-alloc.h"
#if DEBUG
#include <assert.h>
#else
#define assert(x) ((void)0)
#endif
#ifndef MAX
#define MAX(a,b) ((a) >= (b) ? (a) : (b))
#endif
/* Redefine names to avoid conflict with user names */
#define free_list __llalloc_free_list
#define sbrk_start __llalloc_sbrk_start
#define current_mallinfo __llalloc_current_mallinfo
#define ALIGN_TO(size, align) \
(((size) + (align) -1) & ~((align) -1))
/* Alignment of allocated block */
#define MALLOC_ALIGN (4U)
#define CHUNK_ALIGN (sizeof(void*))
#define MALLOC_PADDING ((MAX(MALLOC_ALIGN, CHUNK_ALIGN)) - CHUNK_ALIGN)
/* as well as the minimal allocation size
* to hold a free pointer */
#define MALLOC_MINSIZE (sizeof(void *))
#define MALLOC_PAGE_ALIGN (sizeof(void *))
#define MAX_ALLOC_SIZE (0x4000U)
#define CHUNK_OFFSET ((malloc_size_t)(&(((struct malloc_chunk *)0)->next)))
/* size of smallest possible chunk. A memory piece smaller than this size
* won't be able to create a chunk */
#define MALLOC_MINCHUNK (CHUNK_OFFSET + MALLOC_PADDING + MALLOC_MINSIZE)
/* Forward data declarations */
extern chunk * free_list;
extern char sbrk_start[];
extern struct mallinfo current_mallinfo;
static inline chunk * get_chunk_from_ptr(void * ptr)
{
chunk * c = (chunk *)((char *)ptr - CHUNK_OFFSET);
/* Skip the padding area */
if (c->size < 0) c = (chunk *)((char *)c + c->size);
return c;
}
/* Starting point of memory allocated from system */
char sbrk_start[LL_ARENA_SIZE];
/* List list header of free blocks */
chunk * free_list = (chunk *) &sbrk_start;
void ll_clean_arena() {
// Reset all ram inside the arena
memset(sbrk_start, 0, LL_ARENA_SIZE);
// Make sure the default hasn't been overridden
free_list->size = LL_ARENA_SIZE;
}
/** Function ll_malloc
* Algorithm:
* Walk through the free list to find the first match. If fails to find
* one, call sbrk to allocate a new chunk.
*/
void * ll_malloc(malloc_size_t s)
{
chunk *p, *r;
char * ptr, * align_ptr;
int offset;
malloc_size_t alloc_size;
alloc_size = ALIGN_TO(s, CHUNK_ALIGN); /* size of aligned data load */
alloc_size += MALLOC_PADDING; /* padding */
alloc_size += CHUNK_OFFSET; /* size of chunk head */
alloc_size = MAX(alloc_size, MALLOC_MINCHUNK);
if (alloc_size >= MAX_ALLOC_SIZE || alloc_size < s)
{
errno = ENOMEM;
return NULL;
}
p = free_list;
r = p;
while (r)
{
int rem = r->size - alloc_size;
if (rem >= 0)
{
if (rem >= MALLOC_MINCHUNK)
{
/* Find a chunk that much larger than required size, break
* it into two chunks and return the second one */
r->size = rem;
r = (chunk *)((char *)r + rem);
r->size = alloc_size;
}
/* Find a chunk that is exactly the size or slightly bigger
* than requested size, just return this chunk */
else if (p == r)
{
/* Now it implies p==r==free_list. Move the free_list
* to next chunk */
free_list = r->next;
}
else
{
/* Normal case. Remove it from free_list */
p->next = r->next;
}
break;
}
p=r;
r=r->next;
}
/* Failed to find a appropriate chunk. Ask for more memory */
if (r == NULL)
{
errno = ENOMEM;
return NULL;
}
ptr = (char *)r + CHUNK_OFFSET;
align_ptr = (char *)ALIGN_TO((unsigned long)ptr, MALLOC_ALIGN);
offset = align_ptr - ptr;
if (offset)
{
*(int *)((char *)r + offset) = -offset;
}
assert(align_ptr + size <= (char *)r + alloc_size);
return align_ptr;
}
/** Function ll_free
* Implementation of libc free.
* Algorithm:
* Maintain a global free chunk single link list, headed by global
* variable free_list.
* When free, insert the to-be-freed chunk into free list. The place to
* insert should make sure all chunks are sorted by address from low to
* high. Then merge with neighbor chunks if adjacent.
*/
void ll_free (void * free_p)
{
chunk * p_to_free;
chunk * p, * q;
if (free_p == NULL) return;
p_to_free = get_chunk_from_ptr(free_p);
if (free_list == NULL)
{
/* Set first free list element */
p_to_free->next = free_list;
free_list = p_to_free;
return;
}
if (p_to_free < free_list)
{
if ((char *)p_to_free + p_to_free->size == (char *)free_list)
{
/* Chunk to free is just before the first element of
* free list */
p_to_free->size += free_list->size;
p_to_free->next = free_list->next;
}
else
{
/* Insert before current free_list */
p_to_free->next = free_list;
}
free_list = p_to_free;
return;
}
q = free_list;
/* Walk through the free list to find the place for insert. */
do
{
p = q;
q = q->next;
} while (q && q <= p_to_free);
/* Now p <= p_to_free and either q == NULL or q > p_to_free
* Try to merge with chunks immediately before/after it. */
if ((char *)p + p->size == (char *)p_to_free)
{
/* Chunk to be freed is adjacent
* to a free chunk before it */
p->size += p_to_free->size;
/* If the merged chunk is also adjacent
* to the chunk after it, merge again */
if ((char *)p + p->size == (char *) q)
{
p->size += q->size;
p->next = q->next;
}
}
else if ((char *)p + p->size > (char *)p_to_free)
{
/* Report double free fault */
errno = ENOMEM;
return;
}
else if ((char *)p_to_free + p_to_free->size == (char *) q)
{
/* Chunk to be freed is adjacent
* to a free chunk after it */
p_to_free->size += q->size;
p_to_free->next = q->next;
p->next = p_to_free;
}
else
{
/* Not adjacent to any chunk. Just insert it. Resulting
* a fragment. */
p_to_free->next = q;
p->next = p_to_free;
}
}
/* Function ll_calloc
* Implement calloc simply by calling malloc and set zero */
void * ll_calloc(malloc_size_t n, malloc_size_t elem)
{
void * mem = ll_malloc(n * elem);
if (mem != NULL) memset(mem, 0, n * elem);
return mem;
}
/* Function ll_realloc
* Implement realloc by malloc + memcpy */
void * ll_realloc(void * ptr, malloc_size_t size)
{
void * mem;
// chunk * p_to_realloc;
if (ptr == NULL) return ll_malloc(size);
if (size == 0)
{
ll_free(ptr);
return NULL;
}
/* TODO: There is chance to shrink the chunk if newly requested
* size is much small */
if (ll_malloc_usable_size(ptr) >= size)
return ptr;
mem = ll_malloc(size);
if (mem != NULL)
{
memcpy(mem, ptr, size);
ll_free(ptr);
}
return mem;
}
struct mallinfo current_mallinfo={0,0,0,0,0,0,0,0,0,0};
struct mallinfo ll_mallinfo()
{
chunk * pf;
size_t free_size = 0;
size_t total_size = LL_ARENA_SIZE;
for (pf = free_list; pf; pf = pf->next)
free_size += pf->size;
current_mallinfo.arena = total_size;
current_mallinfo.fordblks = free_size;
current_mallinfo.uordblks = total_size - free_size;
return current_mallinfo;
}
malloc_size_t ll_malloc_usable_size(void * ptr)
{
chunk * c = (chunk *)((char *)ptr - CHUNK_OFFSET);
int size_or_offset = c->size;
if (size_or_offset < 0)
{
/* Padding is used. Excluding the padding size */
c = (chunk *)((char *)c + c->size);
return c->size - CHUNK_OFFSET + size_or_offset;
}
return c->size - CHUNK_OFFSET;
}

58
teensy/lua-alloc.h Normal file
View file

@ -0,0 +1,58 @@
#ifndef __LUALIGHTS_LUA_ALLOC_H
#define __LUALIGHTS_LUA_ALLOC_H
// 24K seems to be an ok amount for now. Might need to expand it
#define LL_ARENA_SIZE 24576
typedef size_t malloc_size_t;
typedef struct malloc_chunk
{
/* ------------------
* chunk->| size (4 bytes) |
* ------------------
* | Padding for |
* | alignment |
* | holding neg |
* | offset to size |
* ------------------
* mem_ptr->| point to next |
* | free when freed|
* | or data load |
* | when allocated |
* ------------------
*/
/* size of the allocated payload area, including size before
CHUNK_OFFSET */
long size;
/* since here, the memory is either the next free block, or data load */
struct malloc_chunk * next;
}chunk;
/* Copied from malloc.h */
struct mallinfo
{
size_t arena; /* total space allocated from system */
size_t ordblks; /* number of non-inuse chunks */
size_t smblks; /* unused -- always zero */
size_t hblks; /* number of mmapped regions */
size_t hblkhd; /* total space in mmapped regions */
size_t usmblks; /* unused -- always zero */
size_t fsmblks; /* unused -- always zero */
size_t uordblks; /* total allocated space */
size_t fordblks; /* total non-inuse space */
size_t keepcost; /* top-most, releasable (via malloc_trim) space */
};
/* Forward function declarations */
extern void * ll_malloc(malloc_size_t);
extern void ll_free (void * free_p);
extern void * ll_calloc(malloc_size_t n, malloc_size_t elem);
extern struct mallinfo ll_mallinfo();
extern malloc_size_t ll_malloc_usable_size(void * ptr);
extern void * ll_realloc(void * ptr, malloc_size_t size);
extern void ll_clean_arena();
#endif

283
teensy/lua.cpp Normal file
View file

@ -0,0 +1,283 @@
#include "log.h"
#include "leds.h"
#include "lua.hpp"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "lua-alloc.h"
/*These three are needed for stubs because something for some god awful reason wants them. Can't find the source of them and they're easier to fix this way*/
int _kill(pid_t pid, int sig) {return 0;}
int _getpid() {return 1;}
int _gettimeofday(struct timeval *tv, struct timezone *tz) {return -1;}
int _open(const char *pathname, int flags) {return -1;}
ssize_t _write(int fd, const void *buf, size_t count) {return -1;}
}
char l_prog_buff[MAX_PRGMSIZE] = "function main()\n"
" local leds = led_data()\n"
" local white = 255 * 65536 + 255 * 256 + 255\n"
" while true do\n"
" for i = 1, 450 do\n"
" leds[i] = white\n"
" end\n"
" end\n"
"end\n";
/* "function main()\n"
" local leds = led_data()\n"
" print \"Hello World\"\n"
" while true do\n"
" \n"
" for g = 0, 255, 5 do\n"
" leds[1] = 255 * 65536 + g * 256\n"
" end\n"
" for r = 255, 0, -5 do\n"
" leds[1] = r * 65536 + 255 * 256\n"
" end\n"
" for b = 0, 255, 5 do\n"
" leds[1] = 255 * 256 + b\n"
" end\n"
" for g = 255, 0, -5 do\n"
" leds[1] = g * 256 + 255\n"
" end\n"
" for r = 0, 255, 5 do\n"
" leds[1] = r * 65536 + 255\n"
" end\n"
" for b = 255, 0, -5 do\n"
" leds[1] = 255 * 65536 + b\n"
" end\n"
" end\n"
"end\n"; */
lua_State *L, *t1;
// predeclarations
void l_start(const char *prgm);
void l_initthread();
extern char __llalloc_sbrk_start[];
static void l_dumpmem() {
uint8_t byte = 0;
LogOut.print("\t\t");
for (int i = 0; i < LL_ARENA_SIZE; i++) {
byte = __llalloc_sbrk_start[i];
LogOut.print(byte, HEX);
}
LogOut.println();
}
static void l_memstats() {
struct mallinfo c= ll_mallinfo();
char buff[64];
sprintf(buff, "->mallinfo: t:%d f:%d u:%d", c.arena, c.fordblks, c.uordblks);
debug_log(buff);
}
// I want to replace this with an arena allocator so that i can get better memory performance in the future
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
l_memstats();
//"\t->alloc called: 12345678 12345678 12345 12345";
char buff[64];
sprintf(buff, "\t->alloc called: %08X %08X %05d %05d", (size_t) ud, (size_t) ptr, osize, nsize);
debug_log(buff);
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
ll_free(ptr);
return NULL;
}
else
return ll_realloc(ptr, nsize);
}
// CREATE ARRAY TYPE AND EXPOSE led_data TO LUA.
// metatable method for handling "array[index]"
static int led_data_index (lua_State* L) {
CRGB** parray = (CRGB **) luaL_checkudata(L, 1, "led_data");
int index = luaL_checkint(L, 2);
lua_pushnumber(L, (*parray)[index-1]);
return 1;
}
// metatable method for handle "array[index] = value"
static int led_data_newindex (lua_State* L) {
CRGB** parray = (CRGB **) luaL_checkudata(L, 1, "led_data");
int index = luaL_checkint(L, 2);
int value = luaL_checkint(L, 3);
(*parray)[index-1] = value;
return 0;
}
void l_yield(lua_State *L, lua_Debug *ar) {
lua_yield(L, 0);
}
static int l_sethook(lua_State *L) {
lua_sethook(L, &l_yield, LUA_MASKCOUNT, 100);
return 0;
}
int full_run(lua_State *L, lua_State *t) {
if (t == NULL)
return -1; // If thread has been cancled don't run!
int rc = lua_resume(t, L, 0);
// TODO this is the all important part where i handle errors, the main function exiting, and make sure yielding went properly
char buff[24];
if (rc == 0) {
// Should this be output log?
debug_log("User supplied function exited successfully. Restarting thread");
l_initthread();
} else if (rc == LUA_ERRRUN) {
output_log("Runtime error: ");
output_log(lua_tostring(t1, -1));
output_log("Halting lua runtime");
t1 = NULL;
} else if (rc != LUA_YIELD) {
sprintf(buff, "rc = %d", rc);
output_log("Unknown error: ");
output_log(buff);
output_log(lua_tostring(t1, -1));
output_log("Halting lua runtime");
t1 = NULL;
}
return rc;
}
static const struct luaL_Reg led_data_metamethods[] = {
{ "__index", led_data_index },
{ "__newindex", led_data_newindex },
{NULL, NULL}
};
// create a metatable for our array type
static void create_array_type(lua_State* L) {
luaL_newmetatable(L, "led_data");
luaL_setfuncs(L, led_data_metamethods, 0);
//lua_setglobal(L, "led_data");
}
// expose an array to lua, by storing it in a userdata with the array metatable
static int expose_array(lua_State* L, CRGB array[]) {
CRGB** parray = (CRGB **) lua_newuserdata(L, sizeof(CRGB**));
*parray = array;
luaL_getmetatable(L, "led_data");
lua_setmetatable(L, -2);
return 1;
}
// test routine which exposes our test array to Lua
static int getarray (lua_State* L) {
return expose_array( L, led_data );
}
int luaopen_array (lua_State* L) {
create_array_type(L);
// make our test routine available to Lua
lua_register(L, "led_data", getarray);
return 0;
}
// This code blatantly stolen and borrowed from lbaselib.c luaB_print
static int l_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) {
const char *s;
size_t l;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
s = lua_tolstring(L, -1, &l); /* get result */
if (s == NULL)
return luaL_error(L,
LUA_QL("tostring") " must return a string to " LUA_QL("print"));
//if (i>1) luai_writestring("\t", 1);
output_log(s);
lua_pop(L, 1); /* pop result */
}
//luai_writeline();
return 0;
}
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
// {LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_STRLIBNAME, luaopen_string},
{LUA_BITLIBNAME, luaopen_bit32},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
{NULL, NULL}
};
void l_openlibs(lua_State *L) {
const luaL_Reg *lib;
/* call open functions from 'loadedlibs' and set results to global table */
for (lib = loadedlibs; lib->func; lib++) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1); /* remove lib */
}
}
// INIT AND FRAME CODE.
void l_init() {
l_start(l_prog_buff);
//l_dumpmem();
}
void l_initthread() {
// Create the coroutine
t1 = lua_newthread(L);
l_sethook(t1);
lua_getglobal(t1, "main");
}
void l_stop() {
if (L != NULL)
lua_close(L);
t1 = NULL;
}
void l_start(const char *prgm) {
ll_clean_arena();
t1 = NULL;
L = lua_newstate(l_alloc, 0);
debug_log("Importing libraries");
l_openlibs(L);
luaopen_array(L);
lua_pushcfunction(L, l_print);
lua_setglobal(L, "print");
debug_log("Libraries imported");
debug_log("Loading program");
int e = luaL_dostring(L, prgm);
if (e) {
output_log("error evaling lua code: ");
output_log(lua_tostring(L, -1));
}
l_initthread();
}
void l_frame() {
full_run(L, t1);
}

12
teensy/lua.hpp Normal file
View file

@ -0,0 +1,12 @@
#ifndef __LUALIGHTS_LUA_H
#define __LUALIGHTS_LUA_H
#define MAX_PRGMSIZE 8192
extern char l_prog_buff[MAX_PRGMSIZE];
void l_init();
void l_frame();
void l_stop();
void l_start(const char *prgm);
#endif

81
teensy/wifi.cpp Normal file
View file

@ -0,0 +1,81 @@
#include <Adafruit_CC3000.h>
#include "log.h"
// These are the interrupt and control pins
#define ADAFRUIT_CC3000_IRQ 8 // MUST be an interrupt pin!
// These can be any two pins
#define ADAFRUIT_CC3000_VBAT 9
#define ADAFRUIT_CC3000_CS 10
// Use hardware SPI for the remaining pins
// On an UNO, SCK = 13, MISO = 12, and MOSI = 11
Adafruit_CC3000 cc3000 = Adafruit_CC3000(ADAFRUIT_CC3000_CS, ADAFRUIT_CC3000_IRQ, ADAFRUIT_CC3000_VBAT,
SPI_CLOCK_DIV4); // you can change this clock speed but DI
#define WLAN_SSID "Scalar24" // cannot be longer than 32 characters!
#define WLAN_PASS "Fb274Gh@12G1"
// Security can be WLAN_SEC_UNSEC, WLAN_SEC_WEP, WLAN_SEC_WPA or WLAN_SEC_WPA2
#define WLAN_SECURITY WLAN_SEC_WPA2
/**************************************************************************/
/*!
@brief Tries to read the IP address and other connection details
*/
/**************************************************************************/
bool displayConnectionDetails(void)
{
uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;
if(!cc3000.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))
{
// Useless for this to be in the output buffer, you couldn't see it
debug_log("Unable to retrieve the IP Address!");
return false;
}
else
{
char buff[64];
sprintf(buff, "IP Addr: %d.%d.%d.%d", (uint) (ipAddress & 0xFF000000) >> 24, (uint) (ipAddress & 0xFF0000) >> 16, (uint) (ipAddress & 0xFF00) >> 8, (uint) (ipAddress & 0xFF));
debug_log(buff);
return true;
}
}
void setup_cc3000() {
/* Initialise the module */
cc3000.setPrinter(NULL); //dynamic_cast<Print *>(&LogOut));
if (!cc3000.begin())
{
debug_log("Unable to initialise the CC3000! Check your wiring?");
while(1);
}
/* Attempt to connect to an access point */
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
debug_log("Failed to connect to AP!");
while(1);
}
while (!cc3000.checkDHCP())
{
delay(100); // ToDo: Insert a DHCP timeout!, could use the motion counter if i init that first..
}
/* Display the IP address DNS, Gateway, etc. */
while (! displayConnectionDetails()) {
delay(1000);
}
}
uint8_t mdns = 0;
void loop_wifi() {
/*
if (!(motion_countup & 0xF) && !mdns) {
LogOut.println(F("mDNS send"));
mdnsAdvertiser(1, "Kitchen", sizeof("Kitchen"));
mdns = 1;
} else {
mdns = 0;
}*/
}

3
teensy/wifi.h Normal file
View file

@ -0,0 +1,3 @@
bool displayConnectionDetails(void);
void setup_cc3000();
void loop_wifi();