Skip to content

pwm improvements #304

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cores/arduino/Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ typedef struct _PinDescription
/* Pins table to be instanciated into variant.cpp */
extern PinDescription g_APinDescription[] ;

extern uint32_t pwmPeriod[4];

#ifdef __cplusplus
} // extern "C"

Expand Down
30 changes: 15 additions & 15 deletions cores/arduino/wiring_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
/* Standard Arduino PWM resolution */
static int _writeResolution = 8;
static int _readResolution = 10;

uint32_t maxResolutionValue = 0xFF;

void analogWriteResolution(int res)
{
_writeResolution = res;
maxResolutionValue = 0xFFFFFFFF >> (32-res);
}

void analogReadResolution(int res)
Expand All @@ -49,7 +50,7 @@ static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to)
return value << (to-from);
}

void analogWrite(uint8_t pin, int val)
void analogWrite(uint8_t pin, uint32_t val)
{
if (! digitalPinHasPWM(pin))
{
Expand All @@ -75,20 +76,12 @@ void analogWrite(uint8_t pin, int val)
} else {
/* PWM for everything in between */
PinDescription *p = &g_APinDescription[pin];
uint32_t hcnt = mapResolution(val, _writeResolution, PWM_RESOLUTION);
uint32_t lcnt = PWM_MAX_DUTY_CYCLE - hcnt;
uint32_t offset;

/* For Arduino Uno compatibilty, we scale up frequency on certain pins */
hcnt >>= p->ulPwmScale;
lcnt >>= p->ulPwmScale;

/* Each count must be > 0 */
if (hcnt < PWM_MIN_DUTY_CYCLE)
hcnt = PWM_MIN_DUTY_CYCLE;
if (lcnt < PWM_MIN_DUTY_CYCLE)
lcnt = PWM_MIN_DUTY_CYCLE;

uint32_t offset;

uint32_t hcnt = (val/(float)maxResolutionValue) * pwmPeriod[p->ulPwmChan];
uint32_t lcnt = pwmPeriod[p->ulPwmChan] - hcnt;

/* Set the high count period (duty cycle) */
offset = ((p->ulPwmChan * QRK_PWM_N_LCNT2_LEN) + QRK_PWM_N_LOAD_COUNT2);
MMIO_REG_VAL(QRK_PWM_BASE_ADDR + offset) = hcnt;
Expand Down Expand Up @@ -145,6 +138,13 @@ uint32_t analogRead(uint32_t pin)

}

void analogWriteFrequency(uint8_t pin, uint32_t freq)
{
//convert frequency to period in clock ticks
PinDescription *p = &g_APinDescription[pin];
pwmPeriod[p->ulPwmChan] = F_CPU / freq;
}

#ifdef __cplusplus
}
#endif
11 changes: 10 additions & 1 deletion cores/arduino/wiring_analog.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ typedef enum _eAnalogReference
AR_DEFAULT,
} eAnalogReference ;

#define PWM_PERIOD 65306 //490 Hz

/*
* \brief Configures the reference voltage used for analog input (i.e. the value used as the top of the input range).
* This function is kept only for compatibility with existing AVR based API.
Expand All @@ -47,7 +49,7 @@ extern void analogReference( eAnalogReference ulMode ) ;
* \param pin
* \param val
*/
extern void analogWrite( uint8_t pin, int val ) ;
extern void analogWrite( uint8_t pin, uint32_t val ) ;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this required (changing the API)? Assuming we're still just looking for a positive integer, can you leave the analogWrite declaration as it was, and instead cast to uint32_t as needed?


/*
* \brief Reads the value from the specified analog pin.
Expand All @@ -72,6 +74,13 @@ extern void analogReadResolution(int res);
*/
extern void analogWriteResolution(int res);

/*
* \brief Set the frequency of analogWrite parameters.
*
* \param res
*/
extern void analogWriteFrequency(uint8_t pin, uint32_t freq);
Copy link
Contributor

@eriknyquist eriknyquist Sep 29, 2016

Choose a reason for hiding this comment

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

would recommend using int for both pin and freq, if possible-- just more Arduino-y :)


#ifdef __cplusplus
}
#endif
Expand Down
1 change: 1 addition & 0 deletions variants/arduino_101/variant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ PinDescription g_APinDescription[]=
{ 3, SOC_GPIO_32, SOC_GPIO, SOC_GPIO_AON_BASE_ADDR, 3, GPIO_MUX_MODE, INVALID, INVALID, INVALID, INPUT_MODE }, // Arduino IO28
} ;

uint32_t pwmPeriod[] = {PWM_PERIOD, PWM_PERIOD/2, PWM_PERIOD/2, PWM_PERIOD};
#ifdef __cplusplus
}
#endif
Expand Down