Prelim code from xmas light project
This commit is contained in:
parent
d8ba4cb814
commit
2abb66a248
22 changed files with 1367 additions and 0 deletions
36
teensy/Lualights.ino
Normal file
36
teensy/Lualights.ino
Normal 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
13
teensy/Makefile
Normal 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
15
teensy/README.md
Normal 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
63
teensy/dispatch.h
Normal 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
6
teensy/docs.h
Normal 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
23
teensy/docs.txt
Normal 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
13
teensy/gen_docs.sh
Executable 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
170
teensy/handlers.h
Normal 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
47
teensy/http_lib.cpp
Normal 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
10
teensy/http_lib.h
Normal 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
12
teensy/int_foot.html
Normal 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
11
teensy/int_head.html
Normal 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
21
teensy/leds.cpp
Normal 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
13
teensy/leds.h
Normal 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
30
teensy/log.h
Normal 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
105
teensy/logs.cpp
Normal 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
342
teensy/lua-alloc.c
Normal 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
58
teensy/lua-alloc.h
Normal 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
283
teensy/lua.cpp
Normal 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
12
teensy/lua.hpp
Normal 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
81
teensy/wifi.cpp
Normal 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
3
teensy/wifi.h
Normal file
|
@ -0,0 +1,3 @@
|
|||
bool displayConnectionDetails(void);
|
||||
void setup_cc3000();
|
||||
void loop_wifi();
|
Loading…
Add table
Reference in a new issue