Allow Software PWM via analogWrite(..., {soft:true})

This commit is contained in:
Gordon Williams 2015-09-11 12:24:57 +01:00
parent 202d28005f
commit 36e46d26b0
10 changed files with 52 additions and 23 deletions

View File

@ -18,6 +18,7 @@
Fix issue where new Array(3.0) wouldn't produce a 3 element array
Keep track of modified area in Graphics (so modules with `.flip()` can be speeded up)
Fix `new Date('December 17, 1995 03:24:00')` - check only first 3 chars of month
Allow Software PWM via `analogWrite(..., {soft:true})`
1v80 : Fix SD card IO that can corrupt SD card on file append since 1v73 (fix #536)
Fix some potential pointer issues in hashlib

View File

@ -337,7 +337,7 @@ JsVar *tv_setup_vga(tv_info_vga *inf) {
tvPinSyncV = inf->pinSyncV;
tvCurrentLine = 0;
//JshPinFunction timer = jshPinAnalogOutput(tvPinSync, 1-0.12 /* */, 31468);
//JshPinFunction timer = jshPinAnalogOutput(tvPinSync, 1-0.12 /* */, 31468, JSAOF_NONE);
//if (!timer) return 0; // couldn't set up the timer
jshPinOutput(tvPinSync, 1); // setup output state

View File

@ -99,7 +99,13 @@ JsVarFloat jshPinAnalog(Pin pin);
/// Returns a quickly-read analog value in the range 0-65535
int jshPinAnalogFast(Pin pin);
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq); // if freq<=0, the default is used
typedef enum {
JSAOF_NONE,
JSAOF_ALLOW_SOFTWARE = 1, // Can use software PWM
JSAOF_FORCE_SOFTWARE = 2, // MUST use software PWM
} JshAnalogOutputFlags;
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags); // if freq<=0, the default is used
void jshPinPulse(Pin pin, bool value, JsVarFloat time);
bool jshCanWatch(Pin pin); ///< Can the given pin be watched? it may not be possible because of conflicts
IOEventFlags jshPinWatch(Pin pin, bool shouldWatch); // start watching pin - return the EXTI associated with it

View File

@ -348,7 +348,10 @@ bool jstPinPWM(JsVarFloat freq, JsVarFloat dutyCycle, Pin pin) {
/// Remove any tasks using the given pin
while (utilTimerRemoveTask(jstPinTaskChecker, (void*)&pin));
// if anything is wrong, exit now
if (dutyCycle<=0 || dutyCycle>=1 || freq<=0) return false;
if (dutyCycle<=0 || dutyCycle>=1 || freq<=0) {
jshPinSetValue(pin, dutyCycle >= 0.5);
return false;
}
JsSysTime period = jshGetTimeFromMilliseconds(1000.0 / freq);
if (period > 0xFFFFFFFF) {
jsWarn("Frequency of %f Hz is too slow", freq);

View File

@ -162,20 +162,31 @@ However only pins connected to an ADC will work (see the datasheet)
"params" : [
["pin","pin",["The pin to use","You can find out which pins to use by looking at [your board's reference page](#boards) and searching for pins with the `PWM` or `DAC` markers."]],
["value","float","A value between 0 and 1"],
["options","JsVar",["An object containing options.","Currently only freq (pulse frequency in Hz) is available: ```analogWrite(A0,0.5,{ freq : 10 });``` ","Note that specifying a frequency will force PWM output, even if the pin has a DAC"]]
["options","JsVar",["An object containing options for analog output - see below"]]
]
}
Set the analog Value of a pin. It will be output using PWM.
Objects can contain:
* `freq` - pulse frequency in Hz, eg. ```analogWrite(A0,0.5,{ freq : 10 });``` - specifying a frequency will force PWM output, even if the pin has a DAC
* `soft` - boolean, If true software PWM is used if available.
* `forceSoft` - boolean, If true software PWM is used even
**Note:** if you didn't call `pinMode` beforehand then this function will also reset pin's state to `"output"`
*/
void jswrap_io_analogWrite(Pin pin, JsVarFloat value, JsVar *options) {
JsVarFloat freq = 0;
JshAnalogOutputFlags flags = JSAOF_NONE;
if (jsvIsObject(options)) {
freq = jsvGetFloatAndUnLock(jsvObjectGetChild(options, "freq", 0));
if (jsvGetBoolAndUnLock(jsvObjectGetChild(options, "forceSoft", 0)))
flags |= JSAOF_FORCE_SOFTWARE;
else if (jsvGetBoolAndUnLock(jsvObjectGetChild(options, "soft", 0)))
flags |= JSAOF_ALLOW_SOFTWARE;
}
jshPinAnalogOutput(pin, value, freq);
jshPinAnalogOutput(pin, value, freq, flags);
}
/*JSON{

View File

@ -122,7 +122,7 @@ JsVarFloat jshPinAnalog(Pin pin) {
int jshPinAnalogFast(Pin pin) {
}
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) { // if freq<=0, the default is used
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used
return JSH_NOTHING;
}

View File

@ -535,7 +535,7 @@ int jshPinAnalogFast(Pin pin) {
return 0;
}
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) { // if freq<=0, the default is used
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used
#ifdef USE_WIRINGPI
// todo pwmSetRange and pwmSetClock for freq?
int v = (int)(value*1024);

View File

@ -169,7 +169,7 @@ JsVarFloat jshPinAnalog(Pin pin) {
return value;
}
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) { // if freq<=0, the default is used
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) { // if freq<=0, the default is used
return JSH_NOTHING;
}

View File

@ -172,7 +172,7 @@ int jshPinAnalogFast(Pin pin) {
return 0;
}
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) {
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq, JshAnalogOutputFlags flags) {
return JSH_NOTHING;
} // if freq<=0, the default is used

View File

@ -1747,11 +1747,12 @@ unsigned int jshGetRandomNumber() {
#endif
}
JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) { // if freq<=0, the default is used
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;
JshPinFunction func = 0;
if (jshIsPinValid(pin)) {
if (jshIsPinValid(pin) && !(flags&JSAOF_FORCE_SOFTWARE)) {
int i;
for (i=0;i<JSH_PININFO_FUNCTIONS;i++) {
if (freq<=0 && JSH_PINFUNCTION_IS_DAC(pinInfo[pin].functions[i])) {
@ -1765,21 +1766,28 @@ JshPinFunction jshPinAnalogOutput(Pin pin, JsVarFloat value, JsVarFloat freq) {
}
if (!func) {
/*jshPrintCapablePins(pin, "PWM Output", JSH_TIMER1, JSH_TIMERMAX, 0,0, false);
#if defined(DACS) && DACS>0
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
jshPrintCapablePins(pin, "PWM Output", JSH_TIMER1, JSH_TIMERMAX, 0,0, false);
#if defined(DACS) && DACS>0
jsiConsolePrint("\nOr pins with DAC output are:\n");
jshPrintCapablePins(pin, 0, JSH_DAC, JSH_DAC, 0,0, false);
jsiConsolePrint("\n");
#endif*/
/* 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);
#endif
if (jshIsPinValid(pin))
jsiConsolePrint("You can also use analogWrite(pin, val, {soft:true}) for Software PWM on this pin\n");
return 0;
}