-
• #2
What about having this global function uploaded? It will toggle any pin:
function toggle(pin) { pin.write(pin, !pin.read(); }
To be on the safe side - NOT make an input pin an output pin - use this code:
function toggle(pin) { if (pin.getMode().indexOf("output") > -1) { pin.write(pin, !pin.read(); } }
...and prototype-based-object-oriented, upload this expression, which will give you the .toggle():
Pin.prototype.toggle = function(){ if (pin.getMode().indexOf("output") > -1) { pin.write(pin, !pin.read(); } }
-
• #3
LEDx.set/reset functions help - were they available before?
Yes, pretty much right since the start :)
I've resisted putting toggle in so far because it's only use is really for LEDs. People think it's just
write(!read())
but in reality it's a bit more nuanced than that becauseread
reads the input register, which is actually different to the current output state (think what happens inopendrain
mode).What @allObjects is suggesting (
this.write(pin, !this.read();
) should work ok for LEDs though. It should be pretty easy to upload that beforehand? -
• #4
I just added a
.toggle
function so it'll be in 1v92 - it's one of those things that's a lot easier to do now than it was when Espruino was first made.It's worth noting that it it doesn't work on the ESP8266 port, because on that the internal
jshPinGetState
function doesn't actually inspect the physical peripheral to find out what state the output register is in. -
• #5
Excellent, thank you! I could see that uploading a bit of code would be easy enough, but to have this available out the box is much better!
-
• #6
@Gordon. For the esp the pin state is saved in array - so that could be used for the toggle.
https://github.com/espruino/Espruino/blob/master/targets/esp8266/jshardware.c#L420
This might just work out of box:
JshPinState jshPinGetState(Pin pin) { //os_printf("> ESP8266: jshPinGetState %d\n", pin); return g_pinState[pin]; }
Once this is up on github, we can take a look and also add it to the esp32 port - or a least document as a todo.
-
• #7
You might want to add:
JshPinState jshPinGetState(Pin pin) { if (GPIO_REG_READ(GPIO_OUT_W1TS_ADDRESS, 1<<pin)) return g_pinState[pin]|JSHPINSTATE_PIN_IS_ON; return g_pinState[pin]; }
I think that'll do it - just depends if that register can be read or not.
Basically
jshPinGetState
needs to be able to tell if the pin is meant to be on.It makes stuff like
digitalWrite(LED1,1);save()
work - which wouldn't have on ESP8266 before -
• #8
Did some tests
GPIO_REG_READ(GPIO_OUT_ADDRESS)>>pin)&1
can be used for this, created PR #1034
-
• #9
merged. So 1v92 should have this in
-
• #10
JshPinState jshPinGetState(Pin pin) { if (GPIO_REG_READ(GPIO_OUT_W1TS_ADDRESS, 1<<pin)) return g_pinState[pin]|JSHPINSTATE_PIN_IS_ON; return g_pinState[pin]; }
If the hardware is getting read - is there any point in using the
g_pinState[pin]
array?And I don't follow why the OR is used?
Thanks
-
• #11
Hi @Wilberforce,
JshPinGetState() now returns pinState "or" JSHPINSTATE_PIN_IS_ON if pin is high.
jswrap_pin_toggle() can use JshPinState() to set
bool on =
-
• #12
Yes - I don't understand why the OR is used, if the hardware is getting read - then that would be sufficient I would have thought?
-
• #13
edit: didn't see the previous posts.
jshPinGetState does a lot more than just return whether the pin is on or off, it does 'pullup'/'input'/'output'/etc - it's what is used for
getPinMode
- so you do need the array.
There's a bit of code required to toggle an LED. The LEDx.set/reset functions help (which I'd not used before getting a Puck - were they available before?), but it struck me that a
LEDx.toggle()
abstraction would be really useful, in general, and especially when sending commands over BLE/between Pucks given the buffer limit.Is this feasible?