Merge remote-tracking branch 'upstream/dev' into dev

This commit is contained in:
devsaurus 2015-07-02 20:49:39 +02:00
commit 414a0478be
5 changed files with 501 additions and 219 deletions

View File

@ -29,6 +29,7 @@
#define LUA_USE_MODULES_MQTT
#define LUA_USE_MODULES_COAP
#define LUA_USE_MODULES_U8G
#define LUA_USE_MODULES_WS2801
#define LUA_USE_MODULES_WS2812
#define LUA_USE_MODULES_CJSON
#define LUA_USE_MODULES_CRYPTO

View File

@ -133,6 +133,14 @@
#define ROM_MODULES_BIT
#endif
#if defined(LUA_USE_MODULES_WS2801)
#define MODULES_WS2801 "ws2801"
#define ROM_MODULES_WS2801 \
_ROM(MODULES_WS2801, luaopen_ws2801, ws2801_map)
#else
#define ROM_MODULES_WS2801
#endif
#if defined(LUA_USE_MODULES_WS2812)
#define MODULES_WS2812 "ws2812"
#define ROM_MODULES_WS2812 \
@ -190,6 +198,7 @@
ROM_MODULES_UART \
ROM_MODULES_OW \
ROM_MODULES_BIT \
ROM_MODULES_WS2801 \
ROM_MODULES_WS2812 \
ROM_MODULES_CJSON \
ROM_MODULES_CRYPTO \

500
app/modules/tmr.c Normal file → Executable file
View File

@ -1,232 +1,358 @@
// Module for interfacing with timer
/*guys, srsly, turn on warnings in the makefile*/
#if defined(__GNUC__)
#pragma GCC diagnostic warning "-Wall"
#pragma GCC diagnostic warning "-Wextra"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
/*-------------------------------------
NEW TIMER API
---------------------------------------
tmr.wdclr() -- not changed
tmr.now() -- not changed
tmr.time() -- not changed
tmr.delay() -- not changed
tmr.alarm() -- not changed
tmr.stop() -- changed, see below. use tmr.unregister for old functionality
tmr.register(id, interval, mode, function)
bind function with timer and set the interval in ms
the mode can be:
tmr.ALARM_SINGLE for a single run alarm
tmr.ALARM_SEMI for a multiple single run alarm
tmr.ALARM_AUTO for a repating alarm
tmr.register does NOT start the timer
tmr.alarm is a tmr.register & tmr.start macro
tmr.unregister(id)
stop alarm, unbind function and clean up memory
not needed for ALARM_SINGLE, as it unregisters itself
tmr.start(id)
ret: bool
start a alarm, returns true on success
tmr.stop(id)
ret: bool
stops a alarm, returns true on success
this call dose not free any memory, to do so use tmr.unregister
stopped alarms can be started with start
tmr.interval(id, interval)
set alarm interval, running alarm will be restarted
tmr.state(id)
ret: (bool, int) or nil
returns alarm status (true=started/false=stopped) and mode
nil if timer is unregistered
tmr.softwd(int)
set a negative value to stop the timer
any other value starts the timer, when the
countdown reaches zero, the device restarts
the timer units are seconds
*/
#define MIN_OPT_LEVEL 2
//#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
#include "lrodefs.h"
#include "c_types.h"
static os_timer_t alarm_timer[NUM_TMR];
static int alarm_timer_cb_ref[NUM_TMR] = {LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF,LUA_NOREF};
static bool alarm_timer_repeat[NUM_TMR]= {0,0,0,0,0,0,0};
#define TIMER_MODE_OFF 3
#define TIMER_MODE_SINGLE 0
#define TIMER_MODE_SEMI 2
#define TIMER_MODE_AUTO 1
#define TIMER_IDLE_FLAG (1<<7)
void alarm_timer_common(lua_State* L, unsigned id){
if(alarm_timer_cb_ref[id] == LUA_NOREF)
return;
lua_rawgeti(L, LUA_REGISTRYINDEX, alarm_timer_cb_ref[id]);
if(alarm_timer_repeat[id]==0)
{
if(alarm_timer_cb_ref[id] != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, alarm_timer_cb_ref[id]);
//well, the following are my assumptions
//why, oh why is there no good documentation
//chinese companies should learn from Atmel
extern void ets_timer_arm_new(os_timer_t* t, uint32_t milliseconds, uint32_t repeat_flag, uint32_t isMstimer);
extern void ets_timer_disarm(os_timer_t* t);
extern void ets_timer_setfn(os_timer_t* t, os_timer_func_t *f, void *arg);
extern void ets_delay_us(uint32_t us);
extern uint32_t system_get_time();
extern uint32_t platform_tmr_exists(uint32_t t);
extern uint32_t system_rtc_clock_cali_proc();
extern uint32_t system_get_rtc_time();
extern void system_restart();
}
lua_call(L, 0, 0);
//in fact lua_State is constant, it's pointless to pass it around
//but hey, whatever, I'll just pass it, still we waste 28B here
typedef struct{
os_timer_t os;
lua_State* L;
sint32_t lua_ref;
uint32_t interval;
uint8_t mode;
}timer_struct_t;
typedef timer_struct_t* timer_t;
//everybody just love unions! riiiiight?
static union {
uint64_t block;
uint32_t part[2];
} rtc_time;
static sint32_t soft_watchdog = -1;
static timer_struct_t alarm_timers[NUM_TMR];
static os_timer_t rtc_timer;
static void alarm_timer_common(void* arg){
timer_t tmr = &alarm_timers[(uint32_t)arg];
if(tmr->lua_ref == LUA_NOREF || tmr->L == NULL)
return;
lua_rawgeti(tmr->L, LUA_REGISTRYINDEX, tmr->lua_ref);
//if the timer was set to single run we clean up after it
if(tmr->mode == TIMER_MODE_SINGLE){
luaL_unref(tmr->L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = LUA_NOREF;
tmr->mode = TIMER_MODE_OFF;
}else if(tmr->mode == TIMER_MODE_SEMI){
tmr->mode |= TIMER_IDLE_FLAG;
}
lua_call(tmr->L, 0, 0);
}
void alarm_timer_cb0(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 0);
// Lua: tmr.delay( us )
static int tmr_delay( lua_State* L ){
sint32_t us = luaL_checkinteger(L, 1);
if(us <= 0)
return luaL_error(L, "wrong arg range");
while(us >= 1000000){
us -= 1000000;
os_delay_us(1000000);
WRITE_PERI_REG(0x60000914, 0x73);
}
if(us>0){
os_delay_us(us);
WRITE_PERI_REG(0x60000914, 0x73);
}
return 0;
}
void alarm_timer_cb1(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 1);
// Lua: tmr.now() , return system timer in us
static int tmr_now(lua_State* L){
uint32_t now = 0x7FFFFFFF & system_get_time();
lua_pushinteger(L, now);
return 1;
}
void alarm_timer_cb2(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 2);
// Lua: tmr.register( id, interval, mode, function )
static int tmr_register(lua_State* L){
uint32_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr, id);
sint32_t interval = luaL_checkinteger(L, 2);
uint8_t mode = luaL_checkinteger(L, 3);
//validate arguments
uint8_t args_valid = interval <= 0
|| (mode != TIMER_MODE_SINGLE && mode != TIMER_MODE_SEMI && mode != TIMER_MODE_AUTO)
|| (lua_type(L, 4) != LUA_TFUNCTION && lua_type(L, 4) != LUA_TLIGHTFUNCTION);
if(args_valid)
return luaL_error(L, "wrong arg range");
//get the lua function reference
lua_pushvalue(L, 4);
sint32_t ref = luaL_ref(L, LUA_REGISTRYINDEX);
timer_t tmr = &alarm_timers[id];
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
ets_timer_disarm(&tmr->os);
//there was a bug in this part, the second part of the following condition was missing
if(tmr->lua_ref != LUA_NOREF && tmr->lua_ref != ref)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = ref;
tmr->mode = mode|TIMER_IDLE_FLAG;
tmr->interval = interval;
tmr->L = L;
ets_timer_setfn(&tmr->os, alarm_timer_common, (void*)id);
return 0;
}
void alarm_timer_cb3(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 3);
// Lua: tmr.start( id )
static int tmr_start(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
//we return false if the timer is not idle
if(!(tmr->mode&TIMER_IDLE_FLAG)){
lua_pushboolean(L, 0);
}else{
tmr->mode &= ~TIMER_IDLE_FLAG;
ets_timer_arm_new(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO, 1);
lua_pushboolean(L, 1);
}
return 1;
}
void alarm_timer_cb4(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 4);
// Lua: tmr.alarm( id, interval, repeat, function )
static int tmr_alarm(lua_State* L){
tmr_register(L);
return tmr_start(L);
}
void alarm_timer_cb5(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 5);
// Lua: tmr.stop( id )
static int tmr_stop(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
//we return false if the timer is idle (of not registered)
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF){
tmr->mode |= TIMER_IDLE_FLAG;
ets_timer_disarm(&tmr->os);
lua_pushboolean(L, 1);
}else{
lua_pushboolean(L, 0);
}
return 1;
}
void alarm_timer_cb6(void *arg){
if( !arg )
return;
alarm_timer_common((lua_State*)arg, 6);
// Lua: tmr.unregister( id )
static int tmr_unregister(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
if(!(tmr->mode & TIMER_IDLE_FLAG) && tmr->mode != TIMER_MODE_OFF)
ets_timer_disarm(&tmr->os);
if(tmr->lua_ref != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, tmr->lua_ref);
tmr->lua_ref = LUA_NOREF;
tmr->mode = TIMER_MODE_OFF;
return 0;
}
typedef void (*alarm_timer_callback)(void *arg);
static alarm_timer_callback alarm_timer_cb[NUM_TMR] = {alarm_timer_cb0,alarm_timer_cb1,alarm_timer_cb2,alarm_timer_cb3,alarm_timer_cb4,alarm_timer_cb5,alarm_timer_cb6};
// Lua: delay( us )
static int tmr_delay( lua_State* L )
{
s32 us;
us = luaL_checkinteger( L, 1 );
if ( us <= 0 )
return luaL_error( L, "wrong arg range" );
if(us<1000000)
{
os_delay_us( us );
WRITE_PERI_REG(0x60000914, 0x73);
return 0;
}
unsigned sec = (unsigned)us / 1000000;
unsigned remain = (unsigned)us % 1000000;
int i = 0;
for(i=0;i<sec;i++){
os_delay_us( 1000000 );
WRITE_PERI_REG(0x60000914, 0x73);
}
if(remain>0)
os_delay_us( remain );
return 0;
// Lua: tmr.interval( id, interval )
static int tmr_interval(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
sint32_t interval = luaL_checkinteger(L, 2);
if(interval <= 0)
return luaL_error(L, "wrong arg range");
if(tmr->mode != TIMER_MODE_OFF){
tmr->interval = interval;
if(!(tmr->mode&TIMER_IDLE_FLAG)){
ets_timer_disarm(&tmr->os);
ets_timer_arm_new(&tmr->os, tmr->interval, tmr->mode==TIMER_MODE_AUTO, 1);
}
}
return 0;
}
// Lua: now() , return system timer in us
static int tmr_now( lua_State* L )
{
unsigned now = 0x7FFFFFFF & system_get_time();
lua_pushinteger( L, now );
return 1;
// Lua: tmr.state( id )
static int tmr_state(lua_State* L){
uint8_t id = luaL_checkinteger(L, 1);
MOD_CHECK_ID(tmr,id);
timer_t tmr = &alarm_timers[id];
if(tmr->mode == TIMER_MODE_OFF){
lua_pushnil(L);
return 1;
}
lua_pushboolean(L, (tmr->mode&TIMER_IDLE_FLAG)==0);
lua_pushinteger(L, tmr->mode&(~TIMER_IDLE_FLAG));
return 2;
}
// Lua: alarm( id, interval, repeat, function )
static int tmr_alarm( lua_State* L )
{
s32 interval;
unsigned repeat = 0;
int stack = 1;
unsigned id = luaL_checkinteger( L, stack );
stack++;
MOD_CHECK_ID( tmr, id );
interval = luaL_checkinteger( L, stack );
stack++;
if ( interval <= 0 )
return luaL_error( L, "wrong arg range" );
if ( lua_isnumber(L, stack) ){
repeat = lua_tointeger(L, stack);
stack++;
if ( repeat != 1 && repeat != 0 )
return luaL_error( L, "wrong arg type" );
alarm_timer_repeat[id]=repeat;
}
// luaL_checkanyfunction(L, stack);
if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){
lua_pushvalue(L, stack); // copy argument (func) to the top of stack
if(alarm_timer_cb_ref[id] != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, alarm_timer_cb_ref[id]);
alarm_timer_cb_ref[id] = luaL_ref(L, LUA_REGISTRYINDEX);
}
os_timer_disarm(&(alarm_timer[id]));
os_timer_setfn(&(alarm_timer[id]), (os_timer_func_t *)(alarm_timer_cb[id]), L);
os_timer_arm(&(alarm_timer[id]), interval, repeat);
return 0;
}
// Lua: stop( id )
static int tmr_stop( lua_State* L )
{
unsigned id = luaL_checkinteger( L, 1 );
MOD_CHECK_ID( tmr, id );
os_timer_disarm(&(alarm_timer[id]));
if(alarm_timer_cb_ref[id] != LUA_NOREF)
luaL_unref(L, LUA_REGISTRYINDEX, alarm_timer_cb_ref[id]);
return 0;
}
/*I left the led comments 'couse I don't know
why they are here*/
// extern void update_key_led();
// Lua: wdclr()
static int tmr_wdclr( lua_State* L )
{
WRITE_PERI_REG(0x60000914, 0x73);
// update_key_led();
return 0;
// Lua: tmr.wdclr()
static int tmr_wdclr( lua_State* L ){
WRITE_PERI_REG(0x60000914, 0x73);
// update_key_led();
return 0;
}
static os_timer_t rtc_timer_updator;
static uint32_t cur_count = 0;
static uint32_t rtc_10ms = 0;
void rtc_timer_update_cb(void *arg){
uint32_t t = (uint32_t)system_get_rtc_time();
uint32_t delta = 0;
if(t>=cur_count){
delta = t-cur_count;
}else{
delta = 0xFFFFFFF - cur_count + t + 1;
}
// uint64_t delta = (t>=cur_count)?(t - cur_count):(0x100000000 + t - cur_count);
// NODE_ERR("%x\n",t);
cur_count = t;
uint32_t c = system_rtc_clock_cali_proc();
uint32_t itg = c >> 12; // ~=5
uint32_t dec = c & 0xFFF; // ~=2ff
rtc_10ms += (delta*itg + ((delta*dec)>>12)) / 10000;
// TODO: store rtc_10ms to rtc memory.
//system_rtc_clock_cali_proc() returns
//a fixed point value (12 bit fraction part)
//it tells how many rtc clock ticks represent 1us.
//the high 64 bits of the uint64_t multiplication
//are unnedded (I did the math)
static uint32_t rtc2sec(uint64_t rtc){
uint64_t aku = system_rtc_clock_cali_proc();
aku *= rtc;
return (aku>>12)/1000000;
}
// Lua: time() , return rtc time in second
static int tmr_time( lua_State* L )
{
uint32_t local = rtc_10ms;
lua_pushinteger( L, ((uint32_t)(local/100)) & 0x7FFFFFFF );
return 1;
//the following function workes, I just wrote it and didn't use it.
/*static uint64_t sec2rtc(uint32_t sec){
uint64_t aku = (1<<20)/system_rtc_clock_cali_proc();
aku *= sec;
return (aku>>8)*1000000;
}*/
inline static void rtc_timer_update(){
uint32_t current = system_get_rtc_time();
if(rtc_time.part[0] > current) //overflow check
rtc_time.part[1]++;
rtc_time.part[0] = current;
}
void rtc_callback(void *arg){
rtc_timer_update();
if(soft_watchdog > 0){
soft_watchdog--;
if(soft_watchdog == 0)
system_restart();
}
}
// Lua: tmr.time() , return rtc time in second
static int tmr_time( lua_State* L ){
rtc_timer_update();
lua_pushinteger(L, rtc2sec(rtc_time.block));
return 1;
}
// Lua: tmr.softwd( value )
static int tmr_softwd( lua_State* L ){
soft_watchdog = luaL_checkinteger(L, 1);
return 0;
}
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE tmr_map[] =
{
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "now" ), LFUNCVAL( tmr_now ) },
{ LSTRKEY( "alarm" ), LFUNCVAL( tmr_alarm ) },
{ LSTRKEY( "stop" ), LFUNCVAL( tmr_stop ) },
{ LSTRKEY( "wdclr" ), LFUNCVAL( tmr_wdclr ) },
{ LSTRKEY( "time" ), LFUNCVAL( tmr_time ) },
#if LUA_OPTIMIZE_MEMORY > 0
const LUA_REG_TYPE tmr_map[] = {
{ LSTRKEY( "delay" ), LFUNCVAL( tmr_delay ) },
{ LSTRKEY( "now" ), LFUNCVAL( tmr_now ) },
{ LSTRKEY( "wdclr" ), LFUNCVAL( tmr_wdclr ) },
{ LSTRKEY( "softwd" ), LFUNCVAL( tmr_softwd ) },
{ LSTRKEY( "time" ), LFUNCVAL( tmr_time ) },
{ LSTRKEY( "register" ), LFUNCVAL ( tmr_register ) },
{ LSTRKEY( "alarm" ), LFUNCVAL( tmr_alarm ) },
{ LSTRKEY( "start" ), LFUNCVAL ( tmr_start ) },
{ LSTRKEY( "stop" ), LFUNCVAL ( tmr_stop ) },
{ LSTRKEY( "unregister" ), LFUNCVAL ( tmr_unregister ) },
{ LSTRKEY( "state" ), LFUNCVAL ( tmr_state ) },
{ LSTRKEY( "interval" ), LFUNCVAL ( tmr_interval) },
#if LUA_OPTIMIZE_MEMORY > 0
{ LSTRKEY( "ALARM_SINGLE" ), LNUMVAL( TIMER_MODE_SINGLE ) },
{ LSTRKEY( "ALARM_SEMI" ), LNUMVAL( TIMER_MODE_SEMI ) },
{ LSTRKEY( "ALARM_AUTO" ), LNUMVAL( TIMER_MODE_AUTO ) },
#endif
{ LNILKEY, LNILVAL }
{ LNILKEY, LNILVAL }
};
LUALIB_API int luaopen_tmr( lua_State *L )
{
int i = 0;
for(i=0;i<NUM_TMR;i++){
os_timer_disarm(&(alarm_timer[i]));
os_timer_setfn(&(alarm_timer[i]), (os_timer_func_t *)(alarm_timer_cb[i]), L);
}
os_timer_disarm(&rtc_timer_updator);
os_timer_setfn(&rtc_timer_updator, (os_timer_func_t *)(rtc_timer_update_cb), NULL);
os_timer_arm(&rtc_timer_updator, 500, 1);
LUALIB_API int luaopen_tmr( lua_State *L ){
int i;
for(i=0; i<NUM_TMR; i++){
alarm_timers[i].lua_ref = LUA_NOREF;
alarm_timers[i].mode = TIMER_MODE_OFF;
ets_timer_disarm(&alarm_timers[i].os);
}
rtc_time.block = 0;
ets_timer_disarm(&rtc_timer);
ets_timer_setfn(&rtc_timer, rtc_callback, NULL);
ets_timer_arm_new(&rtc_timer, 1000, 1, 1);
#if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else // #if LUA_OPTIMIZE_MEMORY > 0
luaL_register( L, AUXLIB_TMR, tmr_map );
// Add constants
return 1;
#endif // #if LUA_OPTIMIZE_MEMORY > 0
return 0;
#else
luaL_register( L, AUXLIB_TMR, tmr_map );
lua_pushvalue( L, -1 );
lua_setmetatable( L, -2 );
MOD_REG_NUMBER( L, "ALARM_SINGLE", TIMER_MODE_SINGLE );
MOD_REG_NUMBER( L, "ALARM_SEMI", TIMER_MODE_SEMI );
MOD_REG_NUMBER( L, "ALARM_AUTO", TIMER_MODE_AUTO );
return 1;
#endif
}

140
app/modules/ws2801.c Normal file
View File

@ -0,0 +1,140 @@
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
#include "c_stdlib.h"
#include "c_string.h"
/**
* Code is based on https://github.com/CHERTS/esp8266-devkit/blob/master/Espressif/examples/EspLightNode/user/ws2801.c
* and provides a similar api as the ws2812 module.
* The current implementation allows the caller to use
* any combination of GPIO0, GPIO2, GPIO4, GPIO5 as clock and data.
*/
#define PIN_CLK_DEFAULT 0
#define PIN_DATA_DEFAULT 2
static uint32_t ws2801_bit_clk;
static uint32_t ws2801_bit_data;
static void ws2801_byte(uint8_t n) {
uint8_t bitmask;
for (bitmask = 0x80; bitmask !=0 ; bitmask >>= 1) {
if (n & bitmask) {
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, ws2801_bit_data);
} else {
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, ws2801_bit_data);
}
GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, ws2801_bit_clk);
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, ws2801_bit_clk);
}
}
static void ws2801_color(uint8_t r, uint8_t g, uint8_t b) {
ws2801_byte(r);
ws2801_byte(g);
ws2801_byte(b);
}
static void ws2801_strip(uint8_t const * data, uint16_t len) {
while (len--) {
ws2801_byte(*(data++));
}
GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, ws2801_bit_data);
}
static void enable_pin_mux(pin) {
// The API only supports setting PERIPHS_IO_MUX on GPIO 0, 2, 4, 5
switch (pin) {
case 0:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0);
break;
case 2:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
break;
case 4:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_GPIO4);
break;
case 5:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO5_U, FUNC_GPIO5);
break;
default:
break;
}
}
/* Lua: ws2801.init(pin_clk, pin_data)
* Sets up the GPIO pins
*
* ws2801.init(0, 2) uses GPIO0 as clock and GPIO2 as data.
* This is the default behavior.
*/
static int ICACHE_FLASH_ATTR ws2801_init_lua(lua_State* L) {
uint32_t pin_clk;
uint32_t pin_data;
uint32_t func_gpio_clk;
uint32_t func_gpio_data;
if (!lua_isnumber(L, 1) || !lua_isnumber(L, 2)) {
// Use default pins if the input is omitted
pin_clk = PIN_CLK_DEFAULT;
pin_data = PIN_DATA_DEFAULT;
} else {
pin_clk = luaL_checkinteger(L, 1);
pin_data = luaL_checkinteger(L, 2);
}
ws2801_bit_clk = 1 << pin_clk;
ws2801_bit_data = 1 << pin_data;
os_delay_us(10);
//Set GPIO pins to output mode
enable_pin_mux(pin_clk);
enable_pin_mux(pin_data);
//Set both GPIOs low low
gpio_output_set(0, ws2801_bit_clk | ws2801_bit_data, ws2801_bit_clk | ws2801_bit_data, 0);
os_delay_us(10);
}
/* Lua: ws2801.write(pin, "string")
* Byte triples in the string are interpreted as R G B values.
* This function does not corrupt your buffer.
*
* ws2801.write(string.char(255, 0, 0)) sets the first LED red.
* ws2801.write(string.char(0, 0, 255):rep(10)) sets ten LEDs blue.
* ws2801.write(string.char(0, 255, 0, 255, 255, 255)) first LED green, second LED white.
*/
static int ICACHE_FLASH_ATTR ws2801_writergb(lua_State* L) {
size_t length;
const char *buffer = luaL_checklstring(L, 1, &length);
os_delay_us(10);
os_intr_lock();
ws2801_strip(buffer, length);
os_intr_unlock();
return 0;
}
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const LUA_REG_TYPE ws2801_map[] =
{
{ LSTRKEY( "write" ), LFUNCVAL( ws2801_writergb )},
{ LSTRKEY( "init" ), LFUNCVAL( ws2801_init_lua )},
{ LNILKEY, LNILVAL}
};
LUALIB_API int luaopen_ws2801(lua_State *L) {
LREGISTER(L, "ws2801", ws2801_map);
return 1;
}

View File

@ -128,38 +128,32 @@ class ESPROM:
def connect(self):
print 'Connecting...'
# RTS = CH_PD (i.e reset)
# DTR = GPIO0
# self._port.setRTS(True)
# self._port.setDTR(True)
# self._port.setRTS(False)
# time.sleep(0.1)
# self._port.setDTR(False)
for _ in xrange(4):
# issue reset-to-bootloader:
# RTS = either CH_PD or nRESET (both active low = chip in reset)
# DTR = GPIO0 (active low = boot to flasher)
self._port.setDTR(False)
self._port.setRTS(True)
time.sleep(0.05)
self._port.setDTR(True)
self._port.setRTS(False)
time.sleep(0.05)
self._port.setDTR(False)
# NodeMCU devkit
self._port.setRTS(True)
self._port.setDTR(True)
time.sleep(0.1)
self._port.setRTS(False)
self._port.setDTR(False)
time.sleep(0.1)
self._port.setRTS(True)
time.sleep(0.1)
self._port.setDTR(True)
self._port.setRTS(False)
time.sleep(0.3)
self._port.setDTR(True)
self._port.timeout = 0.5
for i in xrange(10):
try:
self._port.flushInput()
self._port.flushOutput()
self.sync()
self._port.timeout = 5
return
except:
time.sleep(0.1)
self._port.timeout = 0.3 # worst-case latency timer should be 255ms (probably <20ms)
for _ in xrange(4):
try:
self._port.flushInput()
self._port.flushOutput()
self.sync()
self._port.timeout = 5
return
except:
time.sleep(0.05)
# this is a workaround for the CH340 serial driver on current versions of Linux,
# which seems to sometimes set the serial port up with wrong parameters
self._port.close()
self._port.open()
raise Exception('Failed to connect')
""" Read memory address in target """
@ -268,6 +262,15 @@ class ESPROM:
return data
""" Abuse the loader protocol to force flash to be left in write mode """
def flash_unlock_dio(self):
# Enable flash write mode
self.flash_begin(0, 0)
# Reset the chip rather than call flash_finish(), which would have
# write protected the chip again (why oh why does it do that?!)
self.mem_begin(0,0,0,0x40100000)
self.mem_finish(0x40000080)
""" Perform a chip erase of SPI flash """
def flash_erase(self):
# Trick ROM to initialize SFlash
@ -566,7 +569,10 @@ if __name__ == '__main__':
seq += 1
print
print '\nLeaving...'
esp.flash_finish(False)
if args.flash_mode == 'dio':
esp.flash_unlock_dio()
else:
esp.flash_finish(False)
elif args.operation == 'run':
esp.run()