Skip to content

Commit 5e4eef8

Browse files
author
oclyke
committed
change analogWrite scheme to simply clear the timer then reconfigure
1 parent 4d6816e commit 5e4eef8

File tree

2 files changed

+30
-100
lines changed

2 files changed

+30
-100
lines changed

cores/arduino/ard_sup/analog/ap3_analog.cpp

Lines changed: 28 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,13 @@ static const uint8_t outcfg_tbl[32][4] =
119119
{OUTC(1, 7, 1), OUTC(0, 6, 0), OUTC(1, 7, 0), OUTC(1, 3, 1)}, // CTX31: B7OUT2, A6OUT, B7OUT, B3OUT2
120120
};
121121

122+
#define AP3_MAX_ANALOG_WRITE_WIDTH 0x0000FFFF
123+
122124
uint16_t _analogBits = 10; //10-bit by default
123125
uint8_t _analogWriteBits = 8; // 8-bit by default for writes
124126
uint8_t _servoWriteBits = 8; // 8-bit by default for writes
125127
static bool ap3_adc_initialized = false; // flag to show if the ADC has been initialized
128+
static uint32_t _analogWriteWidth = 0x0000FFFF;
126129

127130
uint16_t analogRead(uint8_t pinNumber)
128131
{
@@ -382,92 +385,6 @@ ap3_err_t ap3_change_channel(uint8_t padNumber)
382385
return AP3_OK;
383386
}
384387

385-
bool ap3_pwm_is_running(uint32_t ui32TimerNumber, uint32_t ui32TimerSegment)
386-
{
387-
volatile uint32_t *pui32ConfigReg;
388-
bool is_enabled = false;
389-
390-
//
391-
// Find the correct control register.
392-
//
393-
pui32ConfigReg = (uint32_t *)CTIMERADDRn(CTIMER, ui32TimerNumber, CTRL0);
394-
395-
//
396-
// Begin critical section while config registers are read and modified.
397-
//
398-
AM_CRITICAL_BEGIN
399-
400-
//
401-
// Read the current value.
402-
//
403-
uint32_t ui32ConfigVal = *pui32ConfigReg;
404-
405-
//
406-
// Check the "enable bit"
407-
//
408-
if (ui32ConfigVal & (CTIMER_CTRL0_TMRA0EN_Msk | CTIMER_CTRL0_TMRB0EN_Msk))
409-
{
410-
is_enabled = true;
411-
}
412-
413-
//
414-
// Done with critical section.
415-
//
416-
AM_CRITICAL_END
417-
418-
return is_enabled;
419-
}
420-
421-
void ap3_pwm_wait_for_pulse(uint32_t timer, uint32_t segment, uint32_t output, uint32_t margin)
422-
{
423-
424-
volatile uint32_t *pui32CompareReg;
425-
volatile uint32_t ctimer_val;
426-
uint32_t cmpr0;
427-
428-
// Only wait if the ctimer is running to avoid a deadlock
429-
if (ap3_pwm_is_running(timer, segment))
430-
{
431-
432-
// Get the comapre register address
433-
if (segment == AM_HAL_CTIMER_TIMERA)
434-
{
435-
if (output == AM_HAL_CTIMER_OUTPUT_NORMAL)
436-
{
437-
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRA0);
438-
}
439-
else
440-
{
441-
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRAUXA0);
442-
}
443-
}
444-
else
445-
{
446-
if (output == AM_HAL_CTIMER_OUTPUT_NORMAL)
447-
{
448-
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRB0);
449-
}
450-
else
451-
{
452-
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRAUXB0);
453-
}
454-
}
455-
456-
// Get the compare value
457-
cmpr0 = ((uint32_t)(*(pui32CompareReg)) & 0x0000FFFF);
458-
459-
if (cmpr0)
460-
{ // Only wait when cmpr0 is greater than 0 to avoid an infinite while loop
461-
// Wait for the timer value to be less than the compare value so that it is safe to change
462-
ctimer_val = am_hal_ctimer_read(timer, segment);
463-
while ((ctimer_val + 0) >= cmpr0)
464-
{
465-
ctimer_val = am_hal_ctimer_read(timer, segment);
466-
}
467-
}
468-
}
469-
}
470-
471388
//**********************************************
472389
// ap3_pwm_output
473390
// - This function allows you to specify an arbitrary pwm output signal with a given frame width (fw) and time high (th).
@@ -582,16 +499,16 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
582499
set_periods = false; // disable setting periods when going into a forced mode
583500
}
584501

585-
// Wait until after high pulse to change the state (avoids inversion)
586-
ap3_pwm_wait_for_pulse(timer, segment, output, 10);
587-
588502
// Configure the pin
589503
am_hal_ctimer_output_config(timer,
590504
segment,
591505
pad,
592506
output,
593507
AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA); //
594508

509+
// clear timer (also stops the timer)
510+
am_hal_ctimer_clear(timer, segment);
511+
595512
// Configure the repeated pulse mode with our clock source
596513
am_hal_ctimer_config_single(timer,
597514
segment,
@@ -641,21 +558,32 @@ ap3_err_t analogWriteResolution(uint8_t res)
641558
return AP3_OK;
642559
}
643560

561+
ap3_err_t analogWriteFrameWidth(uint32_t fw){
562+
_analogWriteWidth = fw;
563+
if(_analogWriteWidth > AP3_MAX_ANALOG_WRITE_WIDTH){
564+
_analogWriteWidth = AP3_MAX_ANALOG_WRITE_WIDTH;
565+
}
566+
return AP3_OK;
567+
}
568+
569+
ap3_err_t analogWriteFrequency(float freq){
570+
_analogWriteWidth = (uint32_t)(12000000 / freq);
571+
Serial.println(_analogWriteWidth);
572+
if(_analogWriteWidth > AP3_MAX_ANALOG_WRITE_WIDTH){
573+
return AP3_ERR;
574+
}
575+
if(_analogWriteWidth < 3){
576+
return AP3_ERR;
577+
}
578+
return AP3_OK;
579+
}
580+
644581
ap3_err_t analogWrite(uint8_t pin, uint32_t val)
645582
{
646583
// Determine the high time based on input value and the current resolution setting
647584
uint32_t clk = AM_HAL_CTIMER_HFRC_12MHZ; // Use an Ambiq HAL provided value to select which clock
648-
uint32_t fw = 0xFFFF; // Choose the frame width in clock periods (32767 -> ~ 180 Hz)
649-
if (val >= ((0x01 << _analogWriteBits) - 1))
650-
{
651-
val = fw; // Enable FORCE1
652-
}
653-
else
654-
{
655-
val <<= (16 - _analogWriteBits); // Shift over the value to fill available resolution
656-
}
657-
658-
return ap3_pwm_output(pin, val, fw, clk);
585+
uint32_t th = (uint32_t)(val * _analogWriteWidth) / ((0x01 << _analogWriteBits) - 1);
586+
return ap3_pwm_output(pin, th, _analogWriteWidth, clk);
659587
}
660588

661589
ap3_err_t servoWriteResolution(uint8_t res)

cores/arduino/ard_sup/ap3_analog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ ap3_err_t analogReadResolution(uint8_t bits);
4747

4848
ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk);
4949
ap3_err_t analogWriteResolution(uint8_t res);
50+
ap3_err_t analogWriteFrameWidth(uint32_t fw);
51+
ap3_err_t analogWriteFrequency(float freq);
5052
ap3_err_t analogWrite(uint8_t pin, uint32_t val);
5153
ap3_err_t servoWriteResolution(uint8_t res);
5254
uint8_t getServoResolution();

0 commit comments

Comments
 (0)