EcmaTC53 / spec

Ecma TC53 spec work
23 stars 9 forks source link

Glitch-free Digital output pin initialization? #35

Open tve opened 1 year ago

tve commented 1 year ago

How can I perform a glitch free initialization? Example: I have a digital I/O pin that is in input mode, that reads high, and I need to turn it into an output pin that is high without causing any glitch to low. I'm probably missing something, but the only option I have is:

ioPin = new Digital({pin: pin_number, mode: Digital.output})
ioPin.write(1)

However, this may cause the pin to be briefly initialized to 0 and only afterwards driven high. To solve this, the pattern I'm familiar with is to be able to pass an initial value into the constructor.

phoddie commented 1 year ago

The approach described isn't guaranteed to work because prior to re-reallocation the digital input instance must first closed, as a pin cannot be shared by multiple I/O instance. Closing the input may change its state.

The solution the committee has agreed is to allow an I/O instance to be transferred from another. That is specified for TCP today, but is intended to be supported for any I/O (the Moddable SDK also implements it for PWM, for example). It looks like this:

dIn = new Digital({pin: 1, mode: Digital.Input});
value = dIn.read();
/// ....other stuff here
dOut = new Digital({from: dIn, mode: Digital.Output});
dOut.write(1);
dIn.read();  // throws, ownership of pin has been transferred from dIn to dOut

That allows for a clean transfer between input and output modes. As you note, the initial value of a Digital Output is indeed undefined. One solution could be an optional argument for the initial value, as you suggest. There may be others... not sure yet.

tve commented 1 year ago

Thanks for the clarification.

Another use-case I commonly have is enabling an output pin without glitch when coming out of sleep. The typical situation is that the ping is either undriven low during sleep (or less commonly has a weak pull-up) and that the system, when it comes out of sleep needs to init the pin as an output without glitch, i.e., without changing the level from the sleep level. In this case there is no input pin to output pin transfer (at least no natural one).

In the case of a "light sleep" where the application state is preserved this can be solved in the Digital implementation as the pin instance can be kept alive through the sleep but in the case of a "deep sleep" where the application is restarted when waking up that is not the case.

dtex commented 1 year ago

Is this a pattern we would use if we want to change any property of the IO instance? For example, changing the baud rate of a serial port, or the frequency of a PWM? What are y'all using it for on PWM?

I recall we discussed having to close() and create a new instance in those cases.

phoddie commented 1 year ago

Is this a pattern we would use if we want to change any property of the IO instance?

Potentially any immutable property, yes. (There's no need to use this for a mutable property, for example format)

For example, changing the baud rate of a serial port, or the frequency of a PWM? What are y'all using it for on PWM?

Correct. On ESP32 PWM, this technique can be used to change the hz and resolution. It is obscure - we mostly use it on the M5Core Ink host to play tones. ;) The baud rate on serial is a good example too, though that's not implemented.