Commit 4911d2db authored by Arnim Läuger's avatar Arnim Läuger
Browse files

Merge pull request #1336 from nodemcu/dev

1.5.1 master drop
parents c8037568 2e109686
...@@ -15,6 +15,7 @@ ifndef PDIR ...@@ -15,6 +15,7 @@ ifndef PDIR
GEN_LIBS = libdriver.a GEN_LIBS = libdriver.a
endif endif
STD_CFLAGS=-std=gnu11 -Wimplicit
############################################################# #############################################################
# Configuration i.e. compile options etc. # Configuration i.e. compile options etc.
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include "driver/key.h" #include "driver/key.h"
LOCAL void key_intr_handler(struct keys_param *keys); LOCAL void ICACHE_RAM_ATTR key_intr_handler(void *arg);
/****************************************************************************** /******************************************************************************
* FunctionName : key_init_single * FunctionName : key_init_single
...@@ -130,8 +130,9 @@ key_50ms_cb(struct single_key_param *single_key) ...@@ -130,8 +130,9 @@ key_50ms_cb(struct single_key_param *single_key)
* Returns : none * Returns : none
*******************************************************************************/ *******************************************************************************/
LOCAL void LOCAL void
key_intr_handler(struct keys_param *keys) key_intr_handler(void *arg)
{ {
struct keys_param *keys = arg;
uint8 i; uint8 i;
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS); uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "os_type.h" #include "os_type.h"
#include "osapi.h" #include "osapi.h"
#include "gpio.h" #include "gpio.h"
#include "hw_timer.h"
#include "user_interface.h" #include "user_interface.h"
#include "driver/pwm.h" #include "driver/pwm.h"
...@@ -21,6 +22,19 @@ ...@@ -21,6 +22,19 @@
// #define PWM_DBG os_printf // #define PWM_DBG os_printf
#define PWM_DBG #define PWM_DBG
// Enabling the next line will cause the interrupt handler to toggle
// this output pin during processing so that the timing is obvious
//
// #define PWM_DBG_PIN 13 // GPIO7
#ifdef PWM_DBG_PIN
#define PWM_DBG_PIN_HIGH() GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, 1 << PWM_DBG_PIN)
#define PWM_DBG_PIN_LOW() GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, 1 << PWM_DBG_PIN)
#else
#define PWM_DBG_PIN_HIGH()
#define PWM_DBG_PIN_LOW()
#endif
LOCAL struct pwm_single_param pwm_single_toggle[2][PWM_CHANNEL + 1]; LOCAL struct pwm_single_param pwm_single_toggle[2][PWM_CHANNEL + 1];
LOCAL struct pwm_single_param *pwm_single; LOCAL struct pwm_single_param *pwm_single;
...@@ -32,7 +46,13 @@ LOCAL int8 pwm_out_io_num[PWM_CHANNEL] = {-1, -1, -1, -1, -1, -1}; ...@@ -32,7 +46,13 @@ LOCAL int8 pwm_out_io_num[PWM_CHANNEL] = {-1, -1, -1, -1, -1, -1};
LOCAL uint8 pwm_channel_toggle[2]; LOCAL uint8 pwm_channel_toggle[2];
LOCAL uint8 *pwm_channel; LOCAL uint8 *pwm_channel;
// Toggle flips between 1 and 0 when we make updates so that the interrupt code
// cn switch cleanly between the two states. The cinterrupt handler uses either
// the pwm_single_toggle[0] or pwm_single_toggle[1]
// pwm_toggle indicates which state should be used on the *next* timer interrupt
// freq boundary.
LOCAL uint8 pwm_toggle = 1; LOCAL uint8 pwm_toggle = 1;
LOCAL volatile uint8 pwm_current_toggle = 1;
LOCAL uint8 pwm_timer_down = 1; LOCAL uint8 pwm_timer_down = 1;
LOCAL uint8 pwm_current_channel = 0; LOCAL uint8 pwm_current_channel = 0;
...@@ -41,27 +61,8 @@ LOCAL uint16 pwm_gpio = 0; ...@@ -41,27 +61,8 @@ LOCAL uint16 pwm_gpio = 0;
LOCAL uint8 pwm_channel_num = 0; LOCAL uint8 pwm_channel_num = 0;
//XXX: 0xffffffff/(80000000/16)=35A LOCAL void ICACHE_RAM_ATTR pwm_tim1_intr_handler(os_param_t p);
#define US_TO_RTC_TIMER_TICKS(t) \ #define TIMER_OWNER ((os_param_t) 'P')
((t) ? \
(((t) > 0x35A) ? \
(((t)>>2) * ((APB_CLK_FREQ>>4)/250000) + ((t)&0x3) * ((APB_CLK_FREQ>>4)/1000000)) : \
(((t) *(APB_CLK_FREQ>>4)) / 1000000)) : \
0)
//FRC1
#define FRC1_ENABLE_TIMER BIT7
typedef enum {
DIVDED_BY_1 = 0,
DIVDED_BY_16 = 4,
DIVDED_BY_256 = 8,
} TIMER_PREDIVED_MODE;
typedef enum {
TM_LEVEL_INT = 1,
TM_EDGE_INT = 0,
} TIMER_INT_MODE;
LOCAL void ICACHE_FLASH_ATTR LOCAL void ICACHE_FLASH_ATTR
pwm_insert_sort(struct pwm_single_param pwm[], uint8 n) pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
...@@ -74,7 +75,6 @@ pwm_insert_sort(struct pwm_single_param pwm[], uint8 n) ...@@ -74,7 +75,6 @@ pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
struct pwm_single_param tmp; struct pwm_single_param tmp;
os_memcpy(&tmp, &pwm[i], sizeof(struct pwm_single_param)); os_memcpy(&tmp, &pwm[i], sizeof(struct pwm_single_param));
os_memcpy(&pwm[i], &pwm[i - 1], sizeof(struct pwm_single_param));
while (tmp.h_time < pwm[j].h_time) { while (tmp.h_time < pwm[j].h_time) {
os_memcpy(&pwm[j + 1], &pwm[j], sizeof(struct pwm_single_param)); os_memcpy(&pwm[j + 1], &pwm[j], sizeof(struct pwm_single_param));
...@@ -89,18 +89,8 @@ pwm_insert_sort(struct pwm_single_param pwm[], uint8 n) ...@@ -89,18 +89,8 @@ pwm_insert_sort(struct pwm_single_param pwm[], uint8 n)
} }
} }
LOCAL volatile uint8 critical = 0; // Returns FALSE if we cannot start
bool ICACHE_FLASH_ATTR
#define LOCK_PWM(c) do { \
while( (c)==1 ); \
(c) = 1; \
} while (0)
#define UNLOCK_PWM(c) do { \
(c) = 0; \
} while (0)
void ICACHE_FLASH_ATTR
pwm_start(void) pwm_start(void)
{ {
uint8 i, j; uint8 i, j;
...@@ -109,10 +99,19 @@ pwm_start(void) ...@@ -109,10 +99,19 @@ pwm_start(void)
PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]); PWM_DBG("pwm_out_io_num[0]:%d,[1]:%d,[2]:%d\n",pwm_out_io_num[0],pwm_out_io_num[1],pwm_out_io_num[2]);
PWM_DBG("pwm.period:%d,pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.period,pwm.duty[0],pwm.duty[1],pwm.duty[2]); PWM_DBG("pwm.period:%d,pwm.duty[0]:%d,[1]:%d,[2]:%d\n",pwm.period,pwm.duty[0],pwm.duty[1],pwm.duty[2]);
LOCK_PWM(critical); // enter critical // First we need to make sure that the interrupt handler is running
// out of the same set of params as we expect
while (!pwm_timer_down && pwm_toggle != pwm_current_toggle) {
os_delay_us(100);
}
if (pwm_timer_down) {
pwm_toggle = pwm_current_toggle;
}
uint8_t new_toggle = pwm_toggle ^ 0x01;
struct pwm_single_param *local_single = pwm_single_toggle[pwm_toggle ^ 0x01]; struct pwm_single_param *local_single = pwm_single_toggle[new_toggle];
uint8 *local_channel = &pwm_channel_toggle[pwm_toggle ^ 0x01]; uint8 *local_channel = &pwm_channel_toggle[new_toggle];
// step 1: init PWM_CHANNEL+1 channels param // step 1: init PWM_CHANNEL+1 channels param
for (i = 0; i < pwm_channel_num; i++) { for (i = 0; i < pwm_channel_num; i++) {
...@@ -132,9 +131,10 @@ pwm_start(void) ...@@ -132,9 +131,10 @@ pwm_start(void)
*local_channel = pwm_channel_num + 1; *local_channel = pwm_channel_num + 1;
PWM_DBG("1channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time); PWM_DBG("1channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
// step 3: combine same duty channels // step 3: combine same duty channels (or nearly the same duty). If there is
// under 2 us between pwm outputs, then treat them as the same.
for (i = pwm_channel_num; i > 0; i--) { for (i = pwm_channel_num; i > 0; i--) {
if (local_single[i].h_time == local_single[i - 1].h_time) { if (local_single[i].h_time <= local_single[i - 1].h_time + US_TO_RTC_TIMER_TICKS(2)) {
local_single[i - 1].gpio_set |= local_single[i].gpio_set; local_single[i - 1].gpio_set |= local_single[i].gpio_set;
local_single[i - 1].gpio_clear |= local_single[i].gpio_clear; local_single[i - 1].gpio_clear |= local_single[i].gpio_clear;
...@@ -166,28 +166,43 @@ pwm_start(void) ...@@ -166,28 +166,43 @@ pwm_start(void)
(*local_channel)--; (*local_channel)--;
} }
// Make the new ones active
pwm_toggle = new_toggle;
// if timer is down, need to set gpio and start timer // if timer is down, need to set gpio and start timer
if (pwm_timer_down == 1) { if (pwm_timer_down == 1) {
pwm_channel = local_channel; pwm_channel = local_channel;
pwm_single = local_single; pwm_single = local_single;
pwm_current_toggle = pwm_toggle;
// start // start
gpio_output_set(local_single[0].gpio_set, local_single[0].gpio_clear, pwm_gpio, 0); gpio_output_set(local_single[0].gpio_set, local_single[0].gpio_clear, pwm_gpio, 0);
// yeah, if all channels' duty is 0 or 255, don't need to start timer, otherwise start... // yeah, if all channels' duty is 0 or 255, don't need to start timer, otherwise start...
if (*local_channel != 1) { if (*local_channel != 1) {
pwm_timer_down = 0; PWM_DBG("Need to setup timer\n");
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, local_single[0].h_time); if (!platform_hw_timer_init(TIMER_OWNER, NMI_SOURCE, FALSE)) {
} return FALSE;
} }
pwm_timer_down = 0;
if (pwm_toggle == 1) { platform_hw_timer_set_func(TIMER_OWNER, pwm_tim1_intr_handler, 0);
pwm_toggle = 0; platform_hw_timer_arm_ticks(TIMER_OWNER, local_single[0].h_time);
} else {
PWM_DBG("Timer left idle\n");
platform_hw_timer_close(TIMER_OWNER);
}
} else { } else {
pwm_toggle = 1; // ensure that all outputs are outputs
gpio_output_set(0, 0, pwm_gpio, 0);
} }
UNLOCK_PWM(critical); // leave critical #ifdef PWM_DBG_PIN
// Enable as output
gpio_output_set(0, 0, 1 << PWM_DBG_PIN, 0);
#endif
PWM_DBG("3channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time); PWM_DBG("3channel:%d,single[0]:%d,[1]:%d,[2]:%d,[3]:%d\n",*local_channel,local_single[0].h_time,local_single[1].h_time,local_single[2].h_time,local_single[3].h_time);
return TRUE;
} }
/****************************************************************************** /******************************************************************************
...@@ -210,7 +225,6 @@ pwm_set_duty(uint16 duty, uint8 channel) ...@@ -210,7 +225,6 @@ pwm_set_duty(uint16 duty, uint8 channel)
if(i==pwm_channel_num) // non found if(i==pwm_channel_num) // non found
return; return;
LOCK_PWM(critical); // enter critical
if (duty < 1) { if (duty < 1) {
pwm.duty[channel] = 0; pwm.duty[channel] = 0;
} else if (duty >= PWM_DEPTH) { } else if (duty >= PWM_DEPTH) {
...@@ -218,7 +232,6 @@ pwm_set_duty(uint16 duty, uint8 channel) ...@@ -218,7 +232,6 @@ pwm_set_duty(uint16 duty, uint8 channel)
} else { } else {
pwm.duty[channel] = duty; pwm.duty[channel] = duty;
} }
UNLOCK_PWM(critical); // leave critical
} }
/****************************************************************************** /******************************************************************************
...@@ -230,7 +243,6 @@ pwm_set_duty(uint16 duty, uint8 channel) ...@@ -230,7 +243,6 @@ pwm_set_duty(uint16 duty, uint8 channel)
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
pwm_set_freq(uint16 freq, uint8 channel) pwm_set_freq(uint16 freq, uint8 channel)
{ {
LOCK_PWM(critical); // enter critical
if (freq > PWM_FREQ_MAX) { if (freq > PWM_FREQ_MAX) {
pwm.freq = PWM_FREQ_MAX; pwm.freq = PWM_FREQ_MAX;
} else if (freq < 1) { } else if (freq < 1) {
...@@ -240,7 +252,6 @@ pwm_set_freq(uint16 freq, uint8 channel) ...@@ -240,7 +252,6 @@ pwm_set_freq(uint16 freq, uint8 channel)
} }
pwm.period = PWM_1S / pwm.freq; pwm.period = PWM_1S / pwm.freq;
UNLOCK_PWM(critical); // leave critical
} }
/****************************************************************************** /******************************************************************************
...@@ -306,35 +317,57 @@ pwm_get_freq(uint8 channel) ...@@ -306,35 +317,57 @@ pwm_get_freq(uint8 channel)
* Returns : NONE * Returns : NONE
*******************************************************************************/ *******************************************************************************/
LOCAL void ICACHE_RAM_ATTR LOCAL void ICACHE_RAM_ATTR
pwm_tim1_intr_handler(void) pwm_tim1_intr_handler(os_param_t p)
{ {
uint8 local_toggle = pwm_toggle; // pwm_toggle may change outside (void)p;
RTC_CLR_REG_MASK(FRC1_INT_ADDRESS, FRC1_INT_CLR_MASK);
if (pwm_current_channel >= (*pwm_channel - 1)) { // *pwm_channel may change outside PWM_DBG_PIN_HIGH();
pwm_single = pwm_single_toggle[local_toggle];
pwm_channel = &pwm_channel_toggle[local_toggle];
gpio_output_set(pwm_single[*pwm_channel - 1].gpio_set, int offset = 0;
pwm_single[*pwm_channel - 1].gpio_clear,
pwm_gpio,
0);
pwm_current_channel = 0; while (1) {
if (pwm_current_channel >= (*pwm_channel - 1)) {
pwm_single = pwm_single_toggle[pwm_toggle];
pwm_channel = &pwm_channel_toggle[pwm_toggle];
pwm_current_toggle = pwm_toggle;
if (*pwm_channel != 1) { gpio_output_set(pwm_single[*pwm_channel - 1].gpio_set,
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time); pwm_single[*pwm_channel - 1].gpio_clear,
} else { 0,
pwm_timer_down = 1; 0);
}
pwm_current_channel = 0;
if (*pwm_channel == 1) {
pwm_timer_down = 1;
break;
}
} else { } else {
gpio_output_set(pwm_single[pwm_current_channel].gpio_set, gpio_output_set(pwm_single[pwm_current_channel].gpio_set,
pwm_single[pwm_current_channel].gpio_clear, pwm_single[pwm_current_channel].gpio_clear,
pwm_gpio, 0); 0, 0);
pwm_current_channel++;
}
pwm_current_channel++; int next_time = pwm_single[pwm_current_channel].h_time;
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, pwm_single[pwm_current_channel].h_time); // Delay now holds the time (in ticks) since when the last timer expiry was
PWM_DBG_PIN_LOW();
int delay = platform_hw_timer_get_delay_ticks(TIMER_OWNER) + 4 - offset;
offset += next_time;
next_time = next_time - delay;
if (next_time > US_TO_RTC_TIMER_TICKS(4)) {
PWM_DBG_PIN_HIGH();
platform_hw_timer_arm_ticks(TIMER_OWNER, next_time);
break;
} }
PWM_DBG_PIN_HIGH();
}
PWM_DBG_PIN_LOW();
} }
/****************************************************************************** /******************************************************************************
...@@ -342,19 +375,13 @@ pwm_tim1_intr_handler(void) ...@@ -342,19 +375,13 @@ pwm_tim1_intr_handler(void)
* Description : pwm gpio, params and timer initialization * Description : pwm gpio, params and timer initialization
* Parameters : uint16 freq : pwm freq param * Parameters : uint16 freq : pwm freq param
* uint16 *duty : each channel's duty * uint16 *duty : each channel's duty
* Returns : NONE * Returns : void
*******************************************************************************/ *******************************************************************************/
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
pwm_init(uint16 freq, uint16 *duty) pwm_init(uint16 freq, uint16 *duty)
{ {
uint8 i; uint8 i;
RTC_REG_WRITE(FRC1_CTRL_ADDRESS, //FRC2_AUTO_RELOAD|
DIVDED_BY_16
| FRC1_ENABLE_TIMER
| TM_EDGE_INT);
RTC_REG_WRITE(FRC1_LOAD_ADDRESS, 0);
// PIN_FUNC_SELECT(PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC); // PIN_FUNC_SELECT(PWM_0_OUT_IO_MUX, PWM_0_OUT_IO_FUNC);
// PIN_FUNC_SELECT(PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC); // PIN_FUNC_SELECT(PWM_1_OUT_IO_MUX, PWM_1_OUT_IO_FUNC);
// PIN_FUNC_SELECT(PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC); // PIN_FUNC_SELECT(PWM_2_OUT_IO_MUX, PWM_2_OUT_IO_FUNC);
...@@ -372,10 +399,8 @@ pwm_init(uint16 freq, uint16 *duty) ...@@ -372,10 +399,8 @@ pwm_init(uint16 freq, uint16 *duty)
// pwm_set_freq_duty(freq, duty); // pwm_set_freq_duty(freq, duty);
pwm_start(); pwm_start();
ETS_FRC_TIMER1_INTR_ATTACH(pwm_tim1_intr_handler, NULL); PWM_DBG("pwm_init returning\n");
TM1_EDGE_INT_ENABLE();
ETS_FRC1_INTR_ENABLE();
} }
bool ICACHE_FLASH_ATTR bool ICACHE_FLASH_ATTR
...@@ -389,14 +414,12 @@ pwm_add(uint8 channel){ ...@@ -389,14 +414,12 @@ pwm_add(uint8 channel){
if(pwm_out_io_num[i]==channel) // already exist if(pwm_out_io_num[i]==channel) // already exist
return true; return true;
if(pwm_out_io_num[i] == -1){ // empty exist if(pwm_out_io_num[i] == -1){ // empty exist
LOCK_PWM(critical); // enter critical
pwm_out_io_num[i] = channel; pwm_out_io_num[i] = channel;
pwm.duty[i] = 0; pwm.duty[i] = 0;
pwm_gpio |= (1 << pin_num[channel]); pwm_gpio |= (1 << pin_num[channel]);
PIN_FUNC_SELECT(pin_mux[channel], pin_func[channel]); PIN_FUNC_SELECT(pin_mux[channel], pin_func[channel]);
GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel]))) & (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain; GPIO_REG_WRITE(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel])), GPIO_REG_READ(GPIO_PIN_ADDR(GPIO_ID_PIN(pin_num[channel]))) & (~ GPIO_PIN_PAD_DRIVER_SET(GPIO_PAD_DRIVER_ENABLE))); //disable open drain;
pwm_channel_num++; pwm_channel_num++;
UNLOCK_PWM(critical); // leave critical
return true; return true;
} }
} }
...@@ -412,7 +435,6 @@ pwm_delete(uint8 channel){ ...@@ -412,7 +435,6 @@ pwm_delete(uint8 channel){
uint8 i,j; uint8 i,j;
for(i=0;i<pwm_channel_num;i++){ for(i=0;i<pwm_channel_num;i++){
if(pwm_out_io_num[i]==channel){ // exist if(pwm_out_io_num[i]==channel){ // exist
LOCK_PWM(critical); // enter critical
pwm_out_io_num[i] = -1; pwm_out_io_num[i] = -1;
pwm_gpio &= ~(1 << pin_num[channel]); //clear the bit pwm_gpio &= ~(1 << pin_num[channel]); //clear the bit
for(j=i;j<pwm_channel_num-1;j++){ for(j=i;j<pwm_channel_num-1;j++){
...@@ -422,7 +444,6 @@ pwm_delete(uint8 channel){ ...@@ -422,7 +444,6 @@ pwm_delete(uint8 channel){
pwm_out_io_num[pwm_channel_num-1] = -1; pwm_out_io_num[pwm_channel_num-1] = -1;
pwm.duty[pwm_channel_num-1] = 0; pwm.duty[pwm_channel_num-1] = 0;
pwm_channel_num--; pwm_channel_num--;
UNLOCK_PWM(critical); // leave critical
return true; return true;
} }
} }
......
/*
* Driver for interfacing to cheap rotary switches that
* have a quadrature output with an optional press button
*
* This sets up the relevant gpio as interrupt and then keeps track of
* the position of the switch in software. Changes are enqueued to task
* level and a task message posted when required. If the queue fills up
* then moves are ignored, but the last press/release will be included.
*
* Philip Gladstone, N1DQ
*/
#include "platform.h"
#include "c_types.h"
#include "../libc/c_stdlib.h"
#include "../libc/c_stdio.h"
#include "driver/rotary.h"
#include "user_interface.h"
#include "task/task.h"
#include "ets_sys.h"
//
// Queue is empty if read == write.
// However, we always want to keep the previous value
// so writing is only allowed if write - read < QUEUE_SIZE - 1
#define QUEUE_SIZE 8
#define GET_LAST_STATUS(d) (d->queue[(d->write_offset-1) & (QUEUE_SIZE - 1)])
#define GET_PREV_STATUS(d) (d->queue[(d->write_offset-2) & (QUEUE_SIZE - 1)])
#define HAS_QUEUED_DATA(d) (d->read_offset < d->write_offset)
#define HAS_QUEUE_SPACE(d) (d->read_offset + QUEUE_SIZE - 1 > d->write_offset)
#define REPLACE_STATUS(d, x) (d->queue[(d->write_offset-1) & (QUEUE_SIZE - 1)] = (rotary_event_t) { (x), system_get_time() })
#define QUEUE_STATUS(d, x) (d->queue[(d->write_offset++) & (QUEUE_SIZE - 1)] = (rotary_event_t) { (x), system_get_time() })
#define GET_READ_STATUS(d) (d->queue[d->read_offset & (QUEUE_SIZE - 1)])
#define ADVANCE_IF_POSSIBLE(d) if (d->read_offset < d->write_offset) { d->read_offset++; }
#define STATUS_IS_PRESSED(x) ((x & 0x80000000) != 0)
typedef struct {
int8_t phase_a_pin;
int8_t phase_b_pin;
int8_t press_pin;
uint32_t read_offset; // Accessed by task
uint32_t write_offset; // Accessed by ISR
uint32_t pin_mask;
uint32_t phase_a;
uint32_t phase_b;
uint32_t press;
uint32_t last_press_change_time;
int tasknumber;
rotary_event_t queue[QUEUE_SIZE];
} DATA;
static DATA *data[ROTARY_CHANNEL_COUNT];
static uint8_t task_queued;
static void set_gpio_bits(void);
static void rotary_clear_pin(int pin)
{
if (pin >= 0) {
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[pin]), GPIO_PIN_INTR_DISABLE);
platform_gpio_mode(pin, PLATFORM_GPIO_INPUT, PLATFORM_GPIO_PULLUP);
}
}
// Just takes the channel number. Cleans up the resources used.
int rotary_close(uint32_t channel)
{
if (channel >= sizeof(data) / sizeof(data[0])) {
return -1;
}
DATA *d = data[channel];
if (!d) {
return 0;
}
data[channel] = NULL;
rotary_clear_pin(d->phase_a_pin);
rotary_clear_pin(d->phase_b_pin);
rotary_clear_pin(d->press_pin);
c_free(d);
set_gpio_bits();
return 0;
}
static uint32_t ICACHE_RAM_ATTR rotary_interrupt(uint32_t ret_gpio_status)
{
// This function really is running at interrupt level with everything
// else masked off. It should take as little time as necessary.
//
//
// This gets the set of pins which have changed status
uint32 gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
int i;
for (i = 0; i < sizeof(data) / sizeof(data[0]); i++) {
DATA *d = data[i];
if (!d || (gpio_status & d->pin_mask) == 0) {
continue;
}
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status & d->pin_mask);
uint32_t bits = GPIO_REG_READ(GPIO_IN_ADDRESS);
uint32_t last_status = GET_LAST_STATUS(d).pos;
uint32_t now = system_get_time();
uint32_t new_status;
new_status = last_status & 0x80000000;
// This is the debounce logic for the press switch. We ignore changes
// for 10ms after a change.
if (now - d->last_press_change_time > 10 * 1000) {
new_status = (bits & d->press) ? 0 : 0x80000000;
if (STATUS_IS_PRESSED(new_status ^ last_status)) {
d->last_press_change_time = now;
}
}
// A B
// 1 1 => 0
// 1 0 => 1
// 0 0 => 2
// 0 1 => 3
int micropos = 2;
if (bits & d->phase_b) {
micropos = 3;
}
if (bits & d->phase_a) {
micropos ^= 3;
}
int32_t rotary_pos = last_status;
switch ((micropos - last_status) & 3) {
case 0:
// No change, nothing to do
break;
case 1:
// Incremented by 1
rotary_pos++;
break;
case 3:
// Decremented by 1
rotary_pos--;
break;
default:
// We missed an interrupt
// We will ignore... but mark it.
rotary_pos += 1000000;
break;
}
new_status |= rotary_pos & 0x7fffffff;
if (last_status != new_status) {
// Either we overwrite the status or we add a new one
if (!HAS_QUEUED_DATA(d)
|| STATUS_IS_PRESSED(last_status ^ new_status)
|| STATUS_IS_PRESSED(last_status ^ GET_PREV_STATUS(d).pos)) {
if (HAS_QUEUE_SPACE(d)) {
QUEUE_STATUS(d, new_status);
if (!task_queued) {
if (task_post_medium(d->tasknumber, (os_param_t) &task_queued)) {
task_queued = 1;
}
}
} else {
REPLACE_STATUS(d, new_status);
}
} else {
REPLACE_STATUS(d, new_status);
}
}
ret_gpio_status &= ~(d->pin_mask);
}
return ret_gpio_status;
}
// The pin numbers are actual platform GPIO numbers
int rotary_setup(uint32_t channel, int phase_a, int phase_b, int press, task_handle_t tasknumber )
{
if (channel >= sizeof(data) / sizeof(data[0])) {
return -1;
}
if (data[channel]) {
if (rotary_close(channel)) {
return -1;
}
}
DATA *d = (DATA *) c_zalloc(sizeof(DATA));
if (!d) {
return -1;
}
data[channel] = d;
int i;
d->tasknumber = tasknumber;
d->phase_a = 1 << pin_num[phase_a];
platform_gpio_mode(phase_a, PLATFORM_GPIO_INT, PLATFORM_GPIO_PULLUP);
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[phase_a]), GPIO_PIN_INTR_ANYEDGE);
d->phase_a_pin = phase_a;
d->phase_b = 1 << pin_num[phase_b];
platform_gpio_mode(phase_b, PLATFORM_GPIO_INT, PLATFORM_GPIO_PULLUP);
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[phase_b]), GPIO_PIN_INTR_ANYEDGE);
d->phase_b_pin = phase_b;
if (press >= 0) {
d->press = 1 << pin_num[press];
platform_gpio_mode(press, PLATFORM_GPIO_INT, PLATFORM_GPIO_PULLUP);
gpio_pin_intr_state_set(GPIO_ID_PIN(pin_num[press]), GPIO_PIN_INTR_ANYEDGE);
}
d->press_pin = press;
d->pin_mask = d->phase_a | d->phase_b | d->press;
set_gpio_bits();
return 0;
}
static void set_gpio_bits()
{
uint32_t bits = 0;
for (int i = 0; i < ROTARY_CHANNEL_COUNT; i++) {
DATA *d = data[i];
if (d) {
bits = bits | d->pin_mask;
}
}
platform_gpio_register_intr_hook(bits, rotary_interrupt);
}
bool rotary_has_queued_event(uint32_t channel)
{
if (channel >= sizeof(data) / sizeof(data[0])) {
return FALSE;
}
DATA *d = data[channel];
if (!d) {
return FALSE;
}
return HAS_QUEUED_DATA(d);
}
// Get the oldest event in the queue and remove it (if possible)
bool rotary_getevent(uint32_t channel, rotary_event_t *resultp)
{
rotary_event_t result = { 0 };
if (channel >= sizeof(data) / sizeof(data[0])) {
return FALSE;
}
DATA *d = data[channel];
if (!d) {
return FALSE;
}
ETS_GPIO_INTR_DISABLE();
bool status = FALSE;
if (HAS_QUEUED_DATA(d)) {
result = GET_READ_STATUS(d);
d->read_offset++;
status = TRUE;
} else {
result = GET_LAST_STATUS(d);
}
ETS_GPIO_INTR_ENABLE();
*resultp = result;
return status;
}
int rotary_getpos(uint32_t channel)
{
if (channel >= sizeof(data) / sizeof(data[0])) {
return -1;
}
DATA *d = data[channel];
if (!d) {
return -1;
}
return GET_LAST_STATUS(d).pos;
}
#include "driver/sigma_delta.h"
void sigma_delta_setup( void )
{
GPIO_REG_WRITE(GPIO_SIGMA_DELTA,
GPIO_SIGMA_DELTA_SET(GPIO_SIGMA_DELTA_ENABLE) |
GPIO_SIGMA_DELTA_TARGET_SET(0x00) |
GPIO_SIGMA_DELTA_PRESCALE_SET(0x00));
}
void sigma_delta_stop( void )
{
GPIO_REG_WRITE(GPIO_SIGMA_DELTA,
GPIO_SIGMA_DELTA_SET(GPIO_SIGMA_DELTA_DISABLE) |
GPIO_SIGMA_DELTA_TARGET_SET(0x00) |
GPIO_SIGMA_DELTA_PRESCALE_SET(0x00) );
}
void sigma_delta_set_prescale_target( sint16 prescale, sint16 target )
{
uint32_t prescale_mask, target_mask;
prescale_mask = prescale >= 0 ? GPIO_SIGMA_DELTA_PRESCALE_MASK : 0x00;
target_mask = target >= 0 ? GPIO_SIGMA_DELTA_TARGET_MASK : 0x00;
// set prescale and target with one register access to avoid glitches
GPIO_REG_WRITE(GPIO_SIGMA_DELTA,
(GPIO_REG_READ(GPIO_SIGMA_DELTA) & ~(prescale_mask | target_mask)) |
(GPIO_SIGMA_DELTA_PRESCALE_SET(prescale) & prescale_mask) |
(GPIO_SIGMA_DELTA_TARGET_SET(target) & target_mask));
}
...@@ -70,37 +70,27 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_ ...@@ -70,37 +70,27 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
if(spi_no>1) return; //handle invalid input number if(spi_no>1) return; //handle invalid input number
if(spi_no==SPI){
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
}
else if(spi_no==HSPI){
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
}
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_RD_BYTE_ORDER|SPI_WR_BYTE_ORDER|SPI_DOUTDIN); SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CS_SETUP|SPI_CS_HOLD|SPI_RD_BYTE_ORDER|SPI_WR_BYTE_ORDER|SPI_DOUTDIN);
//set clock polarity // set clock polarity (Reference: http://bbs.espressif.com/viewtopic.php?f=49&t=1570)
// TODO: This doesn't work // phase is dependent on polarity. See Issue #1161
//if (cpol == 1) { if (cpol == 1) {
// SET_PERI_REG_MASK(SPI_CTRL2(spi_no), (SPI_CK_OUT_HIGH_MODE<<SPI_CK_OUT_HIGH_MODE_S)); SET_PERI_REG_MASK(SPI_PIN(spi_no), SPI_IDLE_EDGE);
//} else { } else {
// SET_PERI_REG_MASK(SPI_CTRL2(spi_no), (SPI_CK_OUT_LOW_MODE<<SPI_CK_OUT_LOW_MODE_S)); CLEAR_PERI_REG_MASK(SPI_PIN(spi_no), SPI_IDLE_EDGE);
//} }
//os_printf("SPI_CTRL2 is %08x\n",READ_PERI_REG(SPI_CTRL2(spi_no)));
//set clock phase //set clock phase
if (cpha == 1) { if (cpha == cpol) {
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE|SPI_CK_I_EDGE); // Mode 3: MOSI is set on falling edge of clock
// Mode 0: MOSI is set on falling edge of clock
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE);
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_I_EDGE);
} else { } else {
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE|SPI_CK_I_EDGE); // Mode 2: MOSI is set on rising edge of clock
// Mode 1: MOSI is set on rising edge of clock
SET_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_OUT_EDGE);
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_CK_I_EDGE);
} }
CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE|SPI_USR_MISO|SPI_USR_ADDR|SPI_USR_COMMAND|SPI_USR_DUMMY); CLEAR_PERI_REG_MASK(SPI_USER(spi_no), SPI_FLASH_MODE|SPI_USR_MISO|SPI_USR_ADDR|SPI_USR_COMMAND|SPI_USR_DUMMY);
...@@ -123,6 +113,21 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_ ...@@ -123,6 +113,21 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
((1&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)| ((1&SPI_CLKCNT_N)<<SPI_CLKCNT_N_S)|
((0&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)| ((0&SPI_CLKCNT_H)<<SPI_CLKCNT_H_S)|
((1&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div ((1&SPI_CLKCNT_L)<<SPI_CLKCNT_L_S)); //clear bit 31,set SPI clock div
if(spi_no==SPI){
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x005);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, 1);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, 1);//configure io to spi mode
}
else if(spi_no==HSPI){
WRITE_PERI_REG(PERIPHS_IO_MUX, 0x105);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 2);//configure io to spi mode
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, 2);//configure io to spi mode
}
} }
/****************************************************************************** /******************************************************************************
...@@ -130,12 +135,12 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_ ...@@ -130,12 +135,12 @@ void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_
* Description : Enter provided data into MOSI buffer. * Description : Enter provided data into MOSI buffer.
* The data is regarded as a sequence of bits with length 'bitlen'. * The data is regarded as a sequence of bits with length 'bitlen'.
* It will be written left-aligned starting from position 'offset'. * It will be written left-aligned starting from position 'offset'.
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid * Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 offset - offset into MOSI buffer (number of bits) * uint16 offset - offset into MOSI buffer (number of bits)
* uint8 bitlen - valid number of bits in data * uint8 bitlen - valid number of bits in data
* uint32 data - data to be written into buffer * uint32 data - data to be written into buffer
*******************************************************************************/ *******************************************************************************/
void spi_mast_set_mosi(uint8 spi_no, uint8 offset, uint8 bitlen, uint32 data) void spi_mast_set_mosi(uint8 spi_no, uint16 offset, uint8 bitlen, uint32 data)
{ {
uint8 wn, wn_offset, wn_bitlen; uint8 wn, wn_offset, wn_bitlen;
uint32 wn_data; uint32 wn_data;
...@@ -188,11 +193,11 @@ void spi_mast_set_mosi(uint8 spi_no, uint8 offset, uint8 bitlen, uint32 data) ...@@ -188,11 +193,11 @@ void spi_mast_set_mosi(uint8 spi_no, uint8 offset, uint8 bitlen, uint32 data)
* Description : Retrieve data from MISO buffer. * Description : Retrieve data from MISO buffer.
* The data is regarded as a sequence of bits with length 'bitlen'. * The data is regarded as a sequence of bits with length 'bitlen'.
* It will be read starting left-aligned from position 'offset'. * It will be read starting left-aligned from position 'offset'.
* Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid * Parameters : uint8 spi_no - SPI module number, Only "SPI" and "HSPI" are valid
* uint8 offset - offset into MISO buffer (number of bits) * uint16 offset - offset into MISO buffer (number of bits)
* uint8 bitlen - requested number of bits in data * uint8 bitlen - requested number of bits in data
*******************************************************************************/ *******************************************************************************/
uint32 spi_mast_get_miso(uint8 spi_no, uint8 offset, uint8 bitlen) uint32 spi_mast_get_miso(uint8 spi_no, uint16 offset, uint8 bitlen)
{ {
uint8 wn, wn_offset, wn_bitlen; uint8 wn, wn_offset, wn_bitlen;
uint32 wn_data = 0; uint32 wn_data = 0;
......
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include "ets_sys.h" #include "ets_sys.h"
#include "osapi.h" #include "osapi.h"
#include "driver/uart.h" #include "driver/uart.h"
#include "task/task.h"
#include "user_config.h" #include "user_config.h"
#include "user_interface.h" #include "user_interface.h"
#include "osapi.h"
#define UART0 0 #define UART0 0
#define UART1 1 #define UART1 1
...@@ -27,12 +29,13 @@ ...@@ -27,12 +29,13 @@
// For event signalling // For event signalling
static uint8 task = USER_TASK_PRIO_MAX; static task_handle_t sig = 0;
static os_signal_t sig;
// UartDev is defined and initialized in rom code. // UartDev is defined and initialized in rom code.
extern UartDevice UartDev; extern UartDevice UartDev;
static os_timer_t autobaud_timer;
LOCAL void ICACHE_RAM_ATTR LOCAL void ICACHE_RAM_ATTR
uart0_rx_intr_handler(void *para); uart0_rx_intr_handler(void *para);
...@@ -248,7 +251,7 @@ uart0_rx_intr_handler(void *para) ...@@ -248,7 +251,7 @@ uart0_rx_intr_handler(void *para)
if (RcvChar == '\r' || RcvChar == '\n' ) { if (RcvChar == '\r' || RcvChar == '\n' ) {
pRxBuff->BuffState = WRITE_OVER; pRxBuff->BuffState = WRITE_OVER;
} }
if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) { if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) {
// overflow ...we may need more error handle here. // overflow ...we may need more error handle here.
pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ; pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ;
...@@ -258,7 +261,7 @@ uart0_rx_intr_handler(void *para) ...@@ -258,7 +261,7 @@ uart0_rx_intr_handler(void *para)
if (pRxBuff->pWritePos == pRxBuff->pReadPos){ // overflow one byte, need push pReadPos one byte ahead if (pRxBuff->pWritePos == pRxBuff->pReadPos){ // overflow one byte, need push pReadPos one byte ahead
if (pRxBuff->pReadPos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) { if (pRxBuff->pReadPos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) {
pRxBuff->pReadPos = pRxBuff->pRcvMsgBuff ; pRxBuff->pReadPos = pRxBuff->pRcvMsgBuff ;
} else { } else {
pRxBuff->pReadPos++; pRxBuff->pReadPos++;
} }
...@@ -267,8 +270,38 @@ uart0_rx_intr_handler(void *para) ...@@ -267,8 +270,38 @@ uart0_rx_intr_handler(void *para)
got_input = true; got_input = true;
} }
if (got_input && task != USER_TASK_PRIO_MAX) if (got_input && sig)
system_os_post (task, sig, UART0); task_post_low (sig, false);
}
static void
uart_autobaud_timeout(void *timer_arg)
{
uint32_t uart_no = (uint32_t) timer_arg;
uint32_t divisor = uart_baudrate_detect(uart_no, 1);
static int called_count = 0;
// Shut off after two minutes to stop wasting CPU cycles if insufficient input received
if (called_count++ > 10 * 60 * 2 || divisor) {
os_timer_disarm(&autobaud_timer);
}
if (divisor) {
uart_div_modify(uart_no, divisor);
}
}
static void
uart_init_autobaud(uint32_t uart_no)
{
os_timer_setfn(&autobaud_timer, uart_autobaud_timeout, (void *) uart_no);
os_timer_arm(&autobaud_timer, 100, TRUE);
}
static void
uart_stop_autobaud()
{
os_timer_disarm(&autobaud_timer);
} }
/****************************************************************************** /******************************************************************************
...@@ -281,9 +314,8 @@ uart0_rx_intr_handler(void *para) ...@@ -281,9 +314,8 @@ uart0_rx_intr_handler(void *para)
* Returns : NONE * Returns : NONE
*******************************************************************************/ *******************************************************************************/
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
uart_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 task_prio, os_signal_t sig_input) uart_init(UartBautRate uart0_br, UartBautRate uart1_br, os_signal_t sig_input)
{ {
task = task_prio;
sig = sig_input; sig = sig_input;
// rom use 74880 baut_rate, here reinitialize // rom use 74880 baut_rate, here reinitialize
...@@ -292,16 +324,17 @@ uart_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 task_prio, os_sign ...@@ -292,16 +324,17 @@ uart_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 task_prio, os_sign
UartDev.baut_rate = uart1_br; UartDev.baut_rate = uart1_br;
uart_config(UART1); uart_config(UART1);
ETS_UART_INTR_ENABLE(); ETS_UART_INTR_ENABLE();
#ifdef BIT_RATE_AUTOBAUD
// install uart1 putc callback uart_init_autobaud(0);
#ifndef NODE_DEBUG
os_install_putc1((void *)uart1_write_char);
#endif #endif
} }
void ICACHE_FLASH_ATTR void ICACHE_FLASH_ATTR
uart_setup(uint8 uart_no) uart_setup(uint8 uart_no)
{ {
#ifdef BIT_RATE_AUTOBAUD
uart_stop_autobaud();
#endif
ETS_UART_INTR_DISABLE(); ETS_UART_INTR_DISABLE();
uart_config(uart_no); uart_config(uart_no);
ETS_UART_INTR_ENABLE(); ETS_UART_INTR_ENABLE();
......
...@@ -12,11 +12,10 @@ ...@@ -12,11 +12,10 @@
# a generated lib/image xxx.a () # a generated lib/image xxx.a ()
# #
ifndef PDIR ifndef PDIR
GEN_LIBS = libhttp.a
GEN_LIBS = libupgrade.a
endif endif
STD_CFLAGS=-std=gnu11 -Wimplicit
############################################################# #############################################################
# Configuration i.e. compile options etc. # Configuration i.e. compile options etc.
...@@ -41,7 +40,9 @@ endif ...@@ -41,7 +40,9 @@ endif
INCLUDES := $(INCLUDES) -I $(PDIR)include INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./ INCLUDES += -I ./
INCLUDES += -I ../../include/ets INCLUDES += -I ./include
INCLUDES += -I ../include
INCLUDES += -I ../../include
PDIR := ../$(PDIR) PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile sinclude $(PDIR)Makefile
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
/*
* FIXME: sprintf->snprintf everywhere.
* FIXME: support null characters in responses.
*/
#include "osapi.h"
#include "user_interface.h"
#include "espconn.h"
#include "mem.h"
#include "limits.h"
#include "httpclient.h"
#include "stdlib.h"
/* Internal state. */
typedef struct request_args_t {
char * hostname;
int port;
bool secure;
char * method;
char * path;
char * headers;
char * post_data;
char * buffer;
int buffer_size;
int timeout;
os_timer_t timeout_timer;
http_callback_t callback_handle;
} request_args_t;
static char * ICACHE_FLASH_ATTR esp_strdup( const char * str )
{
if ( str == NULL )
{
return(NULL);
}
char * new_str = (char *) os_malloc( os_strlen( str ) + 1 ); /* 1 for null character */
if ( new_str == NULL )
{
HTTPCLIENT_DEBUG( "esp_strdup: malloc error" );
return(NULL);
}
os_strcpy( new_str, str );
return(new_str);
}
static int ICACHE_FLASH_ATTR
esp_isupper( char c )
{
return(c >= 'A' && c <= 'Z');
}
static int ICACHE_FLASH_ATTR
esp_isalpha( char c )
{
return( (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') );
}
static int ICACHE_FLASH_ATTR
esp_isspace( char c )
{
return(c == ' ' || c == '\t' || c == '\n' || c == '\12');
}
static int ICACHE_FLASH_ATTR
esp_isdigit( char c )
{
return(c >= '0' && c <= '9');
}
static int ICACHE_FLASH_ATTR http_chunked_decode( const char * chunked, char * decode )
{
int i = 0, j = 0;
int decode_size = 0;
char *str = (char *) chunked;
do
{
char * endstr;
/* [chunk-size] */
i = strtoul( str + j, NULL, 16 );
HTTPCLIENT_DEBUG( "Chunk Size:%d\r\n", i );
if ( i <= 0 )
break;
/* [chunk-size-end-ptr] */
endstr = (char *) os_strstr( str + j, "\r\n" );
/* [chunk-ext] */
j += endstr - (str + j);
/* [CRLF] */
j += 2;
/* [chunk-data] */
decode_size += i;
os_memcpy( (char *) &decode[decode_size - i], (char *) str + j, i );
j += i;
/* [CRLF] */
j += 2;
}
while ( true );
/*
*
* footer CRLF
*
*/
return(j);
}
static void ICACHE_FLASH_ATTR http_receive_callback( void * arg, char * buf, unsigned short len )
{
struct espconn * conn = (struct espconn *) arg;
request_args_t * req = (request_args_t *) conn->reverse;
if ( req->buffer == NULL )
{
return;
}
/* Let's do the equivalent of a realloc(). */
const int new_size = req->buffer_size + len;
char * new_buffer;
if ( new_size > BUFFER_SIZE_MAX || NULL == (new_buffer = (char *) os_malloc( new_size ) ) )
{
HTTPCLIENT_DEBUG( "Response too long (%d)\n", new_size );
req->buffer[0] = '\0'; /* Discard the buffer to avoid using an incomplete response. */
if ( req->secure )
espconn_secure_disconnect( conn );
else
espconn_disconnect( conn );
return; /* The disconnect callback will be called. */
}
os_memcpy( new_buffer, req->buffer, req->buffer_size );
os_memcpy( new_buffer + req->buffer_size - 1 /*overwrite the null character*/, buf, len ); /* Append new data. */
new_buffer[new_size - 1] = '\0'; /* Make sure there is an end of string. */
os_free( req->buffer );
req->buffer = new_buffer;
req->buffer_size = new_size;
}
static void ICACHE_FLASH_ATTR http_send_callback( void * arg )
{
struct espconn * conn = (struct espconn *) arg;
request_args_t * req = (request_args_t *) conn->reverse;
if ( req->post_data == NULL )
{
HTTPCLIENT_DEBUG( "All sent\n" );
}
else
{
/* The headers were sent, now send the contents. */
HTTPCLIENT_DEBUG( "Sending request body\n" );
if ( req->secure )
espconn_secure_send( conn, (uint8_t *) req->post_data, strlen( req->post_data ) );
else
espconn_send( conn, (uint8_t *) req->post_data, strlen( req->post_data ) );
os_free( req->post_data );
req->post_data = NULL;
}
}
static void ICACHE_FLASH_ATTR http_connect_callback( void * arg )
{
HTTPCLIENT_DEBUG( "Connected\n" );
struct espconn * conn = (struct espconn *) arg;
request_args_t * req = (request_args_t *) conn->reverse;
espconn_regist_recvcb( conn, http_receive_callback );
espconn_regist_sentcb( conn, http_send_callback );
char post_headers[32] = "";
if ( req->post_data != NULL ) /* If there is data then add Content-Length header. */
{
os_sprintf( post_headers, "Content-Length: %d\r\n", strlen( req->post_data ) );
}
if(req->headers == NULL) /* Avoid NULL pointer, it may cause exception */
{
req->headers = (char *)os_malloc(sizeof(char));
req->headers[0] = '\0';
}
char buf[69 + strlen( req->method ) + strlen( req->path ) + strlen( req->hostname ) +
strlen( req->headers ) + strlen( post_headers )];
int len = os_sprintf( buf,
"%s %s HTTP/1.1\r\n"
"Host: %s:%d\r\n"
"Connection: close\r\n"
"User-Agent: ESP8266\r\n"
"%s"
"%s"
"\r\n",
req->method, req->path, req->hostname, req->port, req->headers, post_headers );
if ( req->secure )
espconn_secure_send( conn, (uint8_t *) buf, len );
else
espconn_send( conn, (uint8_t *) buf, len );
if(req->headers != NULL)
os_free( req->headers );
req->headers = NULL;
HTTPCLIENT_DEBUG( "Sending request header\n" );
}
static void ICACHE_FLASH_ATTR http_disconnect_callback( void * arg )
{
HTTPCLIENT_DEBUG( "Disconnected\n" );
struct espconn *conn = (struct espconn *) arg;
if ( conn == NULL )
{
return;
}
if ( conn->proto.tcp != NULL )
{
os_free( conn->proto.tcp );
}
if ( conn->reverse != NULL )
{
request_args_t * req = (request_args_t *) conn->reverse;
int http_status = -1;
char * body = "";
// Turn off timeout timer
os_timer_disarm( &(req->timeout_timer) );
if ( req->buffer == NULL )
{
HTTPCLIENT_DEBUG( "Buffer probably shouldn't be NULL\n" );
}
else if ( req->buffer[0] != '\0' )
{
/* FIXME: make sure this is not a partial response, using the Content-Length header. */
const char * version_1_0 = "HTTP/1.0 ";
const char * version_1_1 = "HTTP/1.1 ";
if (( os_strncmp( req->buffer, version_1_0, strlen( version_1_0 ) ) != 0 ) &&
( os_strncmp( req->buffer, version_1_1, strlen( version_1_1 ) ) != 0 ))
{
HTTPCLIENT_DEBUG( "Invalid version in %s\n", req->buffer );
}
else
{
http_status = atoi( req->buffer + strlen( version_1_0 ) );
body = (char *) os_strstr(req->buffer, "\r\n\r\n");
if (NULL == body) {
/* Find missing body */
HTTPCLIENT_DEBUG("Body shouldn't be NULL\n");
/* To avoid NULL body */
body = "";
} else {
/* Skip CR & LF */
body = body + 4;
}
if ( os_strstr( req->buffer, "Transfer-Encoding: chunked" ) )
{
int body_size = req->buffer_size - (body - req->buffer);
char chunked_decode_buffer[body_size];
os_memset( chunked_decode_buffer, 0, body_size );
/* Chuncked data */
http_chunked_decode( body, chunked_decode_buffer );
os_memcpy( body, chunked_decode_buffer, body_size );
}
}
}
if ( req->callback_handle != NULL ) /* Callback is optional. */
{
req->callback_handle( body, http_status, req->buffer );
}
if (req->buffer) {
os_free( req->buffer );
}
os_free( req->hostname );
os_free( req->method );
os_free( req->path );
os_free( req );
}
/* Fix memory leak. */
espconn_delete( conn );
os_free( conn );
}
static void ICACHE_FLASH_ATTR http_error_callback( void *arg, sint8 errType )
{
HTTPCLIENT_DEBUG( "Disconnected with error\n" );
http_disconnect_callback( arg );
}
static void ICACHE_FLASH_ATTR http_timeout_callback( void *arg )
{
HTTPCLIENT_DEBUG( "Connection timeout\n" );
struct espconn * conn = (struct espconn *) arg;
if ( conn == NULL )
{
return;
}
if ( conn->reverse == NULL )
{
return;
}
request_args_t * req = (request_args_t *) conn->reverse;
/* Call disconnect */
if ( req->secure )
espconn_secure_disconnect( conn );
else
espconn_disconnect( conn );
}
static void ICACHE_FLASH_ATTR http_dns_callback( const char * hostname, ip_addr_t * addr, void * arg )
{
request_args_t * req = (request_args_t *) arg;
if ( addr == NULL )
{
HTTPCLIENT_DEBUG( "DNS failed for %s\n", hostname );
if ( req->callback_handle != NULL )
{
req->callback_handle( "", -1, "" );
}
os_free( req );
}
else
{
HTTPCLIENT_DEBUG( "DNS found %s " IPSTR "\n", hostname, IP2STR( addr ) );
struct espconn * conn = (struct espconn *) os_zalloc( sizeof(struct espconn) );
conn->type = ESPCONN_TCP;
conn->state = ESPCONN_NONE;
conn->proto.tcp = (esp_tcp *) os_zalloc( sizeof(esp_tcp) );
conn->proto.tcp->local_port = espconn_port();
conn->proto.tcp->remote_port = req->port;
conn->reverse = req;
os_memcpy( conn->proto.tcp->remote_ip, addr, 4 );
espconn_regist_connectcb( conn, http_connect_callback );
espconn_regist_disconcb( conn, http_disconnect_callback );
espconn_regist_reconcb( conn, http_error_callback );
/* Set connection timeout timer */
os_timer_disarm( &(req->timeout_timer) );
os_timer_setfn( &(req->timeout_timer), (os_timer_func_t *) http_timeout_callback, conn );
os_timer_arm( &(req->timeout_timer), req->timeout, false );
if ( req->secure )
{
espconn_secure_set_size( ESPCONN_CLIENT, 5120 ); /* set SSL buffer size */
espconn_secure_connect( conn );
}
else
{
espconn_connect( conn );
}
}
}
void ICACHE_FLASH_ATTR http_raw_request( const char * hostname, int port, bool secure, const char * method, const char * path, const char * headers, const char * post_data, http_callback_t callback_handle )
{
HTTPCLIENT_DEBUG( "DNS request\n" );
request_args_t * req = (request_args_t *) os_zalloc( sizeof(request_args_t) );
req->hostname = esp_strdup( hostname );
req->port = port;
req->secure = secure;
req->method = esp_strdup( method );
req->path = esp_strdup( path );
req->headers = esp_strdup( headers );
req->post_data = esp_strdup( post_data );
req->buffer_size = 1;
req->buffer = (char *) os_malloc( 1 );
req->buffer[0] = '\0'; /* Empty string. */
req->callback_handle = callback_handle;
req->timeout = HTTP_REQUEST_TIMEOUT_MS;
ip_addr_t addr;
err_t error = espconn_gethostbyname( (struct espconn *) req, /* It seems we don't need a real espconn pointer here. */
hostname, &addr, http_dns_callback );
if ( error == ESPCONN_INPROGRESS )
{
HTTPCLIENT_DEBUG( "DNS pending\n" );
}
else if ( error == ESPCONN_OK )
{
/* Already in the local names table (or hostname was an IP address), execute the callback ourselves. */
http_dns_callback( hostname, &addr, req );
}
else
{
if ( error == ESPCONN_ARG )
{
HTTPCLIENT_DEBUG( "DNS arg error %s\n", hostname );
}else {
HTTPCLIENT_DEBUG( "DNS error code %d\n", error );
}
http_dns_callback( hostname, NULL, req ); /* Handle all DNS errors the same way. */
}
}
/*
* Parse an URL of the form http://host:port/path
* <host> can be a hostname or an IP address
* <port> is optional
*/
void ICACHE_FLASH_ATTR http_request( const char * url, const char * method, const char * headers, const char * post_data, http_callback_t callback_handle )
{
/*
* FIXME: handle HTTP auth with http://user:pass@host/
* FIXME: get rid of the #anchor part if present.
*/
char hostname[128] = "";
int port = 80;
bool secure = false;
bool is_http = os_strncmp( url, "http://", strlen( "http://" ) ) == 0;
bool is_https = os_strncmp( url, "https://", strlen( "https://" ) ) == 0;
if ( is_http )
url += strlen( "http://" ); /* Get rid of the protocol. */
else if ( is_https )
{
port = 443;
secure = true;
url += strlen( "https://" ); /* Get rid of the protocol. */
}
else
{
HTTPCLIENT_DEBUG( "URL is not HTTP or HTTPS %s\n", url );
return;
}
char * path = os_strchr( url, '/' );
if ( path == NULL )
{
path = os_strchr( url, '\0' ); /* Pointer to end of string. */
}
char * colon = os_strchr( url, ':' );
if ( colon > path )
{
colon = NULL; /* Limit the search to characters before the path. */
}
if (path - url >= sizeof(hostname)) {
HTTPCLIENT_DEBUG( "hostname is too long %s\n", url );
return;
}
if ( colon == NULL ) /* The port is not present. */
{
os_memcpy( hostname, url, path - url );
hostname[path - url] = '\0';
}
else
{
port = atoi( colon + 1 );
if ( port == 0 )
{
HTTPCLIENT_DEBUG( "Port error %s\n", url );
return;
}
os_memcpy( hostname, url, colon - url );
hostname[colon - url] = '\0';
}
if ( path[0] == '\0' ) /* Empty path is not allowed. */
{
path = "/";
}
HTTPCLIENT_DEBUG( "hostname=%s\n", hostname );
HTTPCLIENT_DEBUG( "port=%d\n", port );
HTTPCLIENT_DEBUG( "method=%s\n", method );
HTTPCLIENT_DEBUG( "path=%s\n", path );
http_raw_request( hostname, port, secure, method, path, headers, post_data, callback_handle );
}
/*
* Parse an URL of the form http://host:port/path
* <host> can be a hostname or an IP address
* <port> is optional
*/
void ICACHE_FLASH_ATTR http_post( const char * url, const char * headers, const char * post_data, http_callback_t callback_handle )
{
http_request( url, "POST", headers, post_data, callback_handle );
}
void ICACHE_FLASH_ATTR http_get( const char * url, const char * headers, http_callback_t callback_handle )
{
http_request( url, "GET", headers, NULL, callback_handle );
}
void ICACHE_FLASH_ATTR http_delete( const char * url, const char * headers, const char * post_data, http_callback_t callback_handle )
{
http_request( url, "DELETE", headers, post_data, callback_handle );
}
void ICACHE_FLASH_ATTR http_put( const char * url, const char * headers, const char * post_data, http_callback_t callback_handle )
{
http_request( url, "PUT", headers, post_data, callback_handle );
}
void ICACHE_FLASH_ATTR http_callback_example( char * response, int http_status, char * full_response )
{
os_printf( "http_status=%d\n", http_status );
if ( http_status != HTTP_STATUS_GENERIC_ERROR )
{
os_printf( "strlen(full_response)=%d\n", strlen( full_response ) );
os_printf( "response=%s<EOF>\n", response );
}
}
/*
* ----------------------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Martin d'Allens <martin.dallens@gmail.com> wrote this file. As long as you retain
* this notice you can do whatever you want with this stuff. If we meet some day,
* and you think this stuff is worth it, you can buy me a beer in return.
* ----------------------------------------------------------------------------
*/
#ifndef __HTTPCLIENT_H__
#define __HTTPCLIENT_H__
#if defined(GLOBAL_DEBUG_ON)
#define HTTPCLIENT_DEBUG_ON
#endif
#if defined(HTTPCLIENT_DEBUG_ON)
#define HTTPCLIENT_DEBUG(format, ...) os_printf(format, ##__VA_ARGS__)
#else
#define HTTPCLIENT_DEBUG(format, ...)
#endif
#if defined(USES_SDK_BEFORE_V140)
#define espconn_send espconn_sent
#define espconn_secure_send espconn_secure_sent
#endif
/*
* In case of TCP or DNS error the callback is called with this status.
*/
#define HTTP_STATUS_GENERIC_ERROR (-1)
/*
* Size of http responses that will cause an error.
*/
#define BUFFER_SIZE_MAX (0x2000)
/*
* Timeout of http request.
*/
#define HTTP_REQUEST_TIMEOUT_MS (10000)
/*
* "full_response" is a string containing all response headers and the response body.
* "response_body and "http_status" are extracted from "full_response" for convenience.
*
* A successful request corresponds to an HTTP status code of 200 (OK).
* More info at http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
*/
typedef void (* http_callback_t)(char * response_body, int http_status, char * full_response);
/*
* Call this function to skip URL parsing if the arguments are already in separate variables.
*/
void ICACHE_FLASH_ATTR http_raw_request(const char * hostname, int port, bool secure, const char * method, const char * path, const char * headers, const char * post_data, http_callback_t callback_handle);
/*
* Request data from URL use custom method.
* The data should be encoded as any format.
* Try:
* http_request("http://httpbin.org/post", "OPTIONS", "Content-type: text/plain", "Hello world", http_callback_example);
*/
void ICACHE_FLASH_ATTR http_request(const char * url, const char * method, const char * headers, const char * post_data, http_callback_t callback_handle);
/*
* Post data to a web form.
* The data should be encoded as any format.
* Try:
* http_post("http://httpbin.org/post", "Content-type: application/json", "{\"hello\": \"world\"}", http_callback_example);
*/
void ICACHE_FLASH_ATTR http_post(const char * url, const char * headers, const char * post_data, http_callback_t callback_handle);
/*
* Download a web page from its URL.
* Try:
* http_get("http://wtfismyip.com/text", NULL, http_callback_example);
*/
void ICACHE_FLASH_ATTR http_get(const char * url, const char * headers, http_callback_t callback_handle);
/*
* Delete a web page from its URL.
* Try:
* http_delete("http://wtfismyip.com/text", NULL, http_callback_example);
*/
void ICACHE_FLASH_ATTR http_delete(const char * url, const char * headers, const char * post_data, http_callback_t callback_handle);
/*
* Update data to a web form.
* The data should be encoded as any format.
* Try:
* http_put("http://httpbin.org/post", "Content-type: application/json", "{\"hello\": \"world\"}", http_callback_example);
*/
void ICACHE_FLASH_ATTR http_put(const char * url, const char * headers, const char * post_data, http_callback_t callback_handle);
/*
* Output on the UART.
*/
void http_callback_example(char * response, int http_status, char * full_response);
#endif // __HTTPCLIENT_H__
...@@ -38,7 +38,10 @@ ...@@ -38,7 +38,10 @@
#include "c_types.h" #include "c_types.h"
#include "ets_sys.h" #include "ets_sys.h"
#include "osapi.h" #include "osapi.h"
#ifndef EFAULT
#define EFAULT 14 #define EFAULT 14
#endif
//#define LWIP_PROVIDE_ERRNO //#define LWIP_PROVIDE_ERRNO
......
...@@ -33,7 +33,7 @@ struct pwm_param { ...@@ -33,7 +33,7 @@ struct pwm_param {
// #define PWM_2_OUT_IO_FUNC FUNC_GPIO13 // #define PWM_2_OUT_IO_FUNC FUNC_GPIO13
void pwm_init(uint16 freq, uint16 *duty); void pwm_init(uint16 freq, uint16 *duty);
void pwm_start(void); bool pwm_start(void);
void pwm_set_duty(uint16 duty, uint8 channel); void pwm_set_duty(uint16 duty, uint8 channel);
uint16 pwm_get_duty(uint8 channel); uint16 pwm_get_duty(uint8 channel);
......
#ifndef READLINE_APP_H
#define READLINE_APP_H
bool uart_getc(char *c);
#endif /* READLINE_APP_H */
/*
* Definitions to access the Rotary driver
*/
#ifndef __ROTARY_H__
#define __ROTARY_H__
#include "c_types.h"
#define ROTARY_CHANNEL_COUNT 3
typedef struct {
uint32_t pos;
uint32_t time_us;
} rotary_event_t;
int rotary_setup(uint32_t channel, int phaseA, int phaseB, int press, task_handle_t tasknumber);
bool rotary_getevent(uint32_t channel, rotary_event_t *result);
bool rotary_has_queued_event(uint32_t channel);
int rotary_getpos(uint32_t channel);
int rotary_close(uint32_t channel);
#endif
#ifndef SIGMA_DELTA_APP_H
#define SIGMA_DELTA_APP_H
#include "eagle_soc.h"
#include "os_type.h"
void sigma_delta_setup( void );
void sigma_delta_stop( void );
void sigma_delta_set_prescale_target( sint16 prescale, sint16 target );
#endif
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define SPI_APP_H #define SPI_APP_H
#include "spi_register.h" #include "spi_register.h"
#include "ets_sys.h" #include "rom.h"
#include "osapi.h" #include "osapi.h"
#include "uart.h" #include "uart.h"
#include "os_type.h" #include "os_type.h"
...@@ -20,9 +20,9 @@ void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit); ...@@ -20,9 +20,9 @@ void spi_lcd_9bit_write(uint8 spi_no,uint8 high_bit,uint8 low_8bit);
//spi master init funtion //spi master init funtion
void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_div); void spi_master_init(uint8 spi_no, unsigned cpol, unsigned cpha, uint32_t clock_div);
// fill MOSI buffer // fill MOSI buffer
void spi_set_mosi(uint8 spi_no, uint8 offset, uint8 bitlen, uint32 data); void spi_mast_set_mosi(uint8 spi_no, uint16 offset, uint8 bitlen, uint32 data);
// retrieve data from MISO buffer // retrieve data from MISO buffer
uint32 spi_get_miso(uint8 spi_no, uint8 offset, uint8 bitlen); uint32 spi_mast_get_miso(uint8 spi_no, uint16 offset, uint8 bitlen);
// initiate SPI transaction // initiate SPI transaction
void spi_mast_transaction(uint8 spi_no, uint8 cmd_bitlen, uint16 cmd_data, uint8 addr_bitlen, uint32 addr_data, void spi_mast_transaction(uint8 spi_no, uint8 cmd_bitlen, uint16 cmd_data, uint8 addr_bitlen, uint32 addr_data,
uint16 mosi_bitlen, uint8 dummy_bitlen, sint16 miso_bitlen); uint16 mosi_bitlen, uint8 dummy_bitlen, sint16 miso_bitlen);
......
#ifndef __SPI_MASTER_H__
#define __SPI_MASTER_H__
#include "driver/spi_register.h"
/*SPI number define*/
#define SPI 0
#define HSPI 1
void spi_master_init(uint8 spi_no);
void spi_master_9bit_write(uint8 spi_no, uint8 high_bit, uint8 low_8bit);
#endif
...@@ -102,6 +102,7 @@ ...@@ -102,6 +102,7 @@
#define SPI_CS2_DIS (BIT(2)) #define SPI_CS2_DIS (BIT(2))
#define SPI_CS1_DIS (BIT(1)) #define SPI_CS1_DIS (BIT(1))
#define SPI_CS0_DIS (BIT(0)) #define SPI_CS0_DIS (BIT(0))
#define SPI_IDLE_EDGE (BIT(29))
#define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30) #define SPI_SLAVE(i) (REG_SPI_BASE(i) + 0x30)
#define SPI_SYNC_RESET (BIT(31)) #define SPI_SYNC_RESET (BIT(31))
......
...@@ -101,7 +101,7 @@ typedef struct { ...@@ -101,7 +101,7 @@ typedef struct {
int buff_uart_no; //indicate which uart use tx/rx buffer int buff_uart_no; //indicate which uart use tx/rx buffer
} UartDevice; } UartDevice;
void uart_init(UartBautRate uart0_br, UartBautRate uart1_br, uint8 task_prio, os_signal_t sig_input); void uart_init(UartBautRate uart0_br, UartBautRate uart1_br, os_signal_t sig_input);
void uart0_alt(uint8 on); void uart0_alt(uint8 on);
void uart0_sendStr(const char *str); void uart0_sendStr(const char *str);
void uart0_putc(const char c); void uart0_putc(const char c);
......
...@@ -169,7 +169,7 @@ typedef struct _espconn_msg{ ...@@ -169,7 +169,7 @@ typedef struct _espconn_msg{
struct espconn *pespconn; struct espconn *pespconn;
comon_pkt pcommon; comon_pkt pcommon;
uint8 count_opt; uint8 count_opt;
int16_t hs_status; //the status of the handshake sint16_t hs_status; //the status of the handshake
void *preverse; void *preverse;
void *pssl; void *pssl;
struct _espconn_msg *pnext; struct _espconn_msg *pnext;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment