Skip to content

Commit

Permalink
Added remark about Pin() being deprecated
Browse files Browse the repository at this point in the history
Added NodeMCU.Dx constants
Added Serial2 definition
Allowed Serial1.on('data'/etc - when console not on Serial1
Added software PWM (just use by default as no hardware)
  • Loading branch information
gfwilliams committed Feb 18, 2016
1 parent e42ca30 commit cb0232b
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 25 deletions.
3 changes: 2 additions & 1 deletion Makefile
Expand Up @@ -983,7 +983,8 @@ ifdef USE_NET
ifdef USE_ESP8266
DEFINES += -DUSE_ESP8266
WRAPPERSOURCES += libs/network/esp8266/jswrap_esp8266_network.c \
targets/esp8266/jswrap_esp8266.c
targets/esp8266/jswrap_esp8266.c \
targets/esp8266/jswrap_nodemcu.c
INCLUDE += -I$(ROOT)/libs/network/esp8266
SOURCES += \
libs/network/esp8266/network_esp8266.c\
Expand Down
2 changes: 1 addition & 1 deletion boards/ESP8266_BOARD.py
Expand Up @@ -34,7 +34,7 @@
'ram' : 80,
'flash' : 0,
'speed' : 80,
'usart' : 1,
'usart' : 2,
'spi' : 1,
'i2c' : 1,
'adc' : 1,
Expand Down
4 changes: 4 additions & 0 deletions src/jswrap_pin.c
Expand Up @@ -42,6 +42,10 @@ Creates a pin from the given argument (or returns undefined if no argument)
JsVar *jswrap_pin_constructor(JsVar *val) {
Pin pin = jshGetPinFromVar(val);
if (!jshIsPinValid(pin)) return 0;
#ifdef ESP8266
if (jsvIsInt(val) && !jsvIsPin(val))
jsWarn("The Pin() constructor is deprecated. Please use `D%d`, or NodeMCU.Dx instead", pin);
#endif
return jsvNewFromPin(pin);
}

Expand Down
114 changes: 94 additions & 20 deletions targets/esp8266/jshardware.c
Expand Up @@ -61,16 +61,23 @@ typedef long long int64_t;
static bool g_spiInitialized = false;
static int g_lastSPIRead = -1;

// Hardware PWM is broken
#ifdef HARDWARE_PWM
struct PWMRecord {
bool enabled; //!< Has this PWM been enabled previously?
};
static uint32 g_pwmFreq;

static struct PWMRecord g_PWMRecords[JSH_PIN_COUNT];
#else
// Whether a pin is being used for soft PWM or not
BITFIELD_DECL(jshPinSoftPWM, JSH_PIN_COUNT);
#endif

static uint8 g_pinState[JSH_PIN_COUNT];




/**
* Convert a pin id to the corresponding Pin Event id.
*/
Expand Down Expand Up @@ -115,13 +122,19 @@ void jshInit() {

ETS_GPIO_INTR_ENABLE();

#ifndef HARDWARE_PWM
BITFIELD_CLEAR(jshPinSoftPWM);
#endif

// Initialize something for each of the possible pins.
for (int i=0; i<JSH_PIN_COUNT; i++) {
#ifdef HARDWARE_PWM
// For each of the PWM records, flag the PWM as having been not initialized.
g_PWMRecords[i].enabled = false;

#endif
g_pinState[i] = 0;
}

os_printf("< jshInit\n");
} // End of jshInit

Expand Down Expand Up @@ -339,6 +352,13 @@ void jshPinSetState(
Pin pin, //!< The pin to have its state changed.
JshPinState state //!< The new desired state of the pin.
) {
/* Make sure we kill software PWM if we set the pin state
* after we've started it */
if (BITFIELD_GET(jshPinSoftPWM, pin)) {
BITFIELD_SET(jshPinSoftPWM, pin, 0);
jstPinPWM(0,0,pin);
}

//os_printf("> ESP8266: jshPinSetState %d, %s, pup=%d, od=%d\n",
// pin, pinStateToString(state), JSHPINSTATE_IS_PULLUP(state), JSHPINSTATE_IS_OPENDRAIN(state));

Expand Down Expand Up @@ -435,28 +455,26 @@ bool CALLED_FROM_INTERRUPT jshPinGetValue( // can be called at interrupt time
}


/**
*
*/
JsVarFloat jshPinAnalog(Pin pin) {
//os_printf("> ESP8266: jshPinAnalog: pin=%d\n", pin);
return (JsVarFloat) system_adc_read();
return (JsVarFloat)system_adc_read() / 1023.0;

This comment has been minimized.

Copy link
@tve

tve Feb 19, 2016

Contributor

Not terribly important, but why 1023 and not 1024? At least the docs state "in units of 1/1024 V".

This comment has been minimized.

Copy link
@gfwilliams

gfwilliams Feb 19, 2016

Author Member

Yeah, I wasn't sure. Docs say 0..1, so I assumed inclusive. It's also what I do for STM32: https://github.com/espruino/Espruino/blob/master/targets/stm32/jshardware.c#L1620

}


/**
*
*/
int jshPinAnalogFast(Pin pin) {
//os_printf("> ESP8266: jshPinAnalogFast: pin=%d\n", pin);
return (JsVarFloat) system_adc_read();
return (int)system_adc_read() << 6; // left-align to 16 bits

This comment has been minimized.

Copy link
@tve

tve Feb 19, 2016

Contributor

I think it would be good to update the comments in jshardware.h https://github.com/espruino/Espruino/blob/master/src/jshardware.h#L166-L171 to explain what really gets returned. For example, it says that jsPinAnalog returns a value between 0 and 1 but not what range that's supposed to represent. Or should it return the voltage? On the esp it would be the same, but on a system whose ADC can measure 0-3.3v or 0-5v that would be different. Similarly, it doesn't explain what the 0..65535 returned by jshPinAnalogFast are supposed to represent.

This comment has been minimized.

Copy link
@gfwilliams

gfwilliams Feb 19, 2016

Author Member

Yeah, that could do with some tweaking. I've just filed a bug for it. The value should just be the full range of the ADC. jshReadVRef should return what voltage 1 actually represents.

Ideally jshPinAnalogFast should just be 65535x what jshPinAnalog is - but i'll stick that in the docs when I get time.

This comment has been minimized.

Copy link
@gfwilliams

gfwilliams Feb 19, 2016

Author Member

It'd be nice to be more explicit, but jshPinAnalogFast is supposed to do a quick conversion - which wouldn't be very accurate anyway :)

}


/**
* Set the output PWM value.
*/
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used
if (value<0) value=0;
if (value>1) value=1;
if (!isfinite(freq)) freq=0;

#ifdef HARDWARE_PWM
os_printf("> jshPinAnalogOutput - jshPinAnalogOutput: pin=%d, value(x100)=%d, freq=%d\n", pin, (int)(value*100), (int)freq);
// Check that the value is between 0.0 and 1.0
if (value < 0 || value > 1.0) {
Expand Down Expand Up @@ -491,17 +509,35 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, Js
os_printf(" - Duty: %d (units of 45 nsecs)\n", duty);
pwm_set_duty(duty, 0);

//jsError("No DAC");
#else
// Software PWM

if (jshIsPinValid(pin)/* && (flags&(JSAOF_ALLOW_SOFTWARE|JSAOF_FORCE_SOFTWARE))*/) {
/* we set the bit field here so that if the user changes the pin state
* later on, we can get rid of the IRQs */
if (!jshGetPinStateIsManual(pin)) {
BITFIELD_SET(jshPinSoftPWM, pin, 0);
jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
}
BITFIELD_SET(jshPinSoftPWM, pin, 1);
if (freq<=0) freq=50;
jstPinPWM(freq, value, pin);
return 0;
}

// Otherwise
//if (jshIsPinValid(pin))
// jsiConsolePrint("You need to use analogWrite(pin, val, {soft:true}) for Software PWM on this pin\n");
return 0;
#endif
}


/**
*
*/
void jshSetOutputValue(JshPinFunction func, int value) {
os_printf("ESP8266: jshSetOutputValue %d %d\n", func, value);
jsError("No DAC");
os_printf("ESP8266: jshSetOutputValue %d %d - unimplemented\n", func, value);
}


Expand Down Expand Up @@ -571,8 +607,7 @@ void jshPinPulse(
#if 1
// Implementation using busy-waiting. Ugly and if the pulse train exceeds 10ms one risks WDT
// resets, but it actually works...
//jshPinSetState(pin, JSHPINSTATE_GPIO_OUT);
jshPinSetValue(pin, pulsePolarity);
jshPinOutput(pin, pulsePolarity);

This comment has been minimized.

Copy link
@tve

tve Feb 19, 2016

Contributor

Is this what you want, it prevents generating pulses on open-collector pins, doesn't it?

This comment has been minimized.

Copy link
@gfwilliams

gfwilliams Feb 19, 2016

Author Member

Nope, it doesn't :) I think this might have been why a lot of the ESP8266 port behaves differently.

jshPinOutput sets the pin to an output if pinMode hasn't been called previously. It means people can just pick up digitalPulse and use it (much like digitalWrite/Read/etc). However if they're used to Arduino and they call pinMode first, that'll work too.

jshDelayMicroseconds(jshGetTimeFromMilliseconds(pulseTime)-6); // -6 adjustment is for overhead
jshPinSetValue(pin, !pulsePolarity);
#endif
Expand Down Expand Up @@ -648,10 +683,48 @@ bool jshIsEventForPin(

//===== USART and Serial =====

/**
*
*/


void jshUSARTSetup(IOEventFlags device, JshUSARTInfo *inf) {
uint8 uart_no;
if (device == EV_SERIAL1) uart_no = UART0;
else if (device == EV_SERIAL2) uart_no = UART1;
else {
jsError("jshUSARTSetup Unknown device %d\n", device);
return;
}

extern void uart_config(uint8 uart_no);
extern UartDevice UartDev;

UartDev.baut_rate = inf->baudRate;
if (inf->bytesize == 5)
UartDev.data_bits = FIVE_BITS;
else if (inf->bytesize == 6)
UartDev.data_bits = SIX_BITS;
else if (inf->bytesize == 7)
UartDev.data_bits = SEVEN_BITS;
else if (inf->bytesize == 8)
UartDev.data_bits = EIGHT_BITS;
else assert(0);
if (inf->parity == 1) {
UartDev.exist_parity = STICK_PARITY_EN;
UartDev.parity = EVEN_BITS;
} else if (inf->parity == 2) {
UartDev.exist_parity = STICK_PARITY_EN;
UartDev.parity = ODD_BITS;
} else {
UartDev.exist_parity = STICK_PARITY_DIS;
UartDev.parity = NONE_BITS;
}
if (inf->stopbits == 1)
UartDev.stop_bits = ONE_STOP_BIT;
else if (inf->stopbits == 2)
UartDev.stop_bits = TWO_STOP_BIT;
else assert(0);
UartDev.flow_ctrl = NONE_CTRL;

uart_config(uart_no);
}

bool jshIsUSBSERIALConnected() {
Expand Down Expand Up @@ -1029,7 +1102,8 @@ void jshUtilTimerDisable() {
}

void jshUtilTimerStart(JsSysTime period) {
if (period < 100.0 || period > 10000) os_printf("UStimer arm %ldus\n", (uint32_t)period);
//if (period < 100.0 || period > 10000) os_printf("UStimer arm %ldus\n", (uint32_t)period);
if (period<1) period=1;
os_timer_arm_us(&utilTimer, (uint32_t)period, 0);
}

Expand Down
53 changes: 53 additions & 0 deletions targets/esp8266/jswrap_nodemcu.c
@@ -0,0 +1,53 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2014 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* This file is designed to be parsed during the build process
*
* NodeMCU-specific pin namings
* ----------------------------------------------------------------------------
*/

#include "jswrap_nodemcu.h"

/*JSON{
"type" : "class",
"class" : "NodeMCU"
}
This is the built-in class for NodeMCU's random ESP8266 pin namings
*/

// TODO: Sigh - because everyone is using `Pin(..)` now, we can't have a proper 'A0' pin defined because it'd shift all the pins created by`Pin(..)`

/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "A0", "generate_full" : "0", "return" : ["pin","A Pin"]
}*/

/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D0", "generate_full" : "16", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D1", "generate_full" : "5", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D2", "generate_full" : "4", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D3", "generate_full" : "0", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D4", "generate_full" : "2", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D5", "generate_full" : "14", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D6", "generate_full" : "12", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D7", "generate_full" : "13", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D8", "generate_full" : "15", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D9", "generate_full" : "3", "return" : ["pin","A Pin"]
}*/
/*JSON{"type" : "staticproperty","class" : "NodeMCU","name" : "D10", "generate_full" : "1", "return" : ["pin","A Pin"]
}*/

13 changes: 13 additions & 0 deletions targets/esp8266/jswrap_nodemcu.h
@@ -0,0 +1,13 @@
/*
* This file is part of Espruino, a JavaScript interpreter for Microcontrollers
*
* Copyright (C) 2014 Gordon Williams <gw@pur3.co.uk>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* ----------------------------------------------------------------------------
* NodeMCU-specific pin namings
* ----------------------------------------------------------------------------
*/
4 changes: 2 additions & 2 deletions targets/esp8266/uart.c
Expand Up @@ -71,7 +71,7 @@ LOCAL void uart0_rx_intr_handler(void *para);
* Parameters : uart_no, use UART0 or UART1 defined ahead
* Returns : NONE
*******************************************************************************/
LOCAL void ICACHE_FLASH_ATTR
void ICACHE_FLASH_ATTR
uart_config(uint8 uart_no)
{
if (uart_no == UART1){
Expand Down Expand Up @@ -339,7 +339,7 @@ uart_recvTask(os_event_t *events)
//already move uart buffer output to uart empty interrupt
//tx_start_uart_buffer(UART0);
#else

// TODO: is this UART1 RX, or TX?

This comment has been minimized.

Copy link
@tve

tve Feb 19, 2016

Contributor

uart_recvTask is for RX only because no TX interrupts are used (the code has provisions for it but it's all ifdef-ed out) and uart1 doesn't have RX (pins used to access the flash chip)

This comment has been minimized.

Copy link
@gfwilliams

gfwilliams Feb 19, 2016

Author Member

Thanks! So this would use UART1 RX, but that's not available?

#endif
}
}
Expand Down
2 changes: 1 addition & 1 deletion targets/esp8266/user_main.c
Expand Up @@ -192,7 +192,7 @@ static void eventHandler(
char pBuffer[100];
int size = getRXBuffer(pBuffer, sizeof(pBuffer));
if (size > 0) {
jshPushIOCharEvents(jsiGetConsoleDevice(), pBuffer, size);
jshPushIOCharEvents(EV_SERIAL1, pBuffer, size);
}
}
break;
Expand Down

1 comment on commit cb0232b

@tve
Copy link
Contributor

@tve tve commented on cb0232b Feb 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for taking a crack at the esp serial!

Please sign in to comment.