Skip to content

Commit 67cea24

Browse files
committed
Merge branch 'master' into Servo
2 parents a335fd6 + 82089ed commit 67cea24

File tree

8 files changed

+205
-64
lines changed

8 files changed

+205
-64
lines changed

README.md

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,38 @@
33

44
## Contents
55

6-
* [Development Status]()
76
* [Installation]()
7+
* [Development Status]()
88
* [Issue Template]()
99
* [Repo Contents]()
1010
* [Acknowledgements]()
1111

12+
13+
## Installation
14+
15+
The structure of this repo is such that it will most closely resemble the structure required when it is time to add it to the Arduino boards manager. Until then you'll have to use the manual installation process.
16+
17+
* [Using Arduino IDE Boards Manager](https://github.com/sparkfun/Arduino_Boards) (Reccomended)
18+
* Follow the instructions at the [SparkFun Arduino Boards Repo](https://github.com/sparkfun/Arduino_Boards)
19+
* Open 'Boards Manager' and select 'SparkFun Apollo3 Boards,' install the latest version.
20+
* JSON boards manager link for convenience: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json
21+
22+
23+
* [Manually Install in Arduino Sketchbook]()
24+
* **First** Install the Arduino SAMD Boards through the Arduino Board Manager. This is required for the ARM Cortex-M toolchain.
25+
* Open your Arduno sketchbook folder, listed in Arduino's preferences pane (it is where your libraries folder lives)
26+
* If there is no ```hardware``` folder create it
27+
* Inside the ```hardware``` folder create ```SparkFun```
28+
* Choose to clone with Git or download the .zip of this repo
29+
* Cloning
30+
* Clone this repo into ```SparkFun``` and give it the name ```apollo3```
31+
* .ZIP
32+
* Download the .ZIP of this repository
33+
* Within ```SparkFun``` create the ```apollo3``` directory
34+
* Unzip the contents of the .ZIP into the ```apollo3``` directory
35+
* Restart Arduino IDE for good measure
36+
37+
1238
## Development Status
1339

1440
The basic necesseties are in-place. This means that you can compile and upload code to your Apollo3 board. Development can be done with the whole range of Hardware Abstraction Layer functions provided in the AmbiqSuite Software Development Kit (based on Release2.1.0).
@@ -35,30 +61,6 @@ Current focus is to begin building support for the essential Arduino libraries i
3561
* Working: transfers with SPISettings.
3662

3763

38-
## Installation
39-
40-
41-
The structure of this repo is such that it will most closely resemble the structure required when it is time to add it to the Arduino boards manager. Until then you'll have to use the manual installation process.
42-
43-
* [Using Arduino IDE Boards Manager](https://github.com/sparkfun/Arduino_Boards) (Reccomended)
44-
* Follow the instructions at the [SparkFun Arduino Boards Repo](https://github.com/sparkfun/Arduino_Boards)
45-
* Open 'Boards Manager' and select 'SparkFun Apollo3 Boards,' install the latest version.
46-
* JSON boards manager link for convenience: https://raw.githubusercontent.com/sparkfun/Arduino_Boards/master/IDE_Board_Manager/package_sparkfun_index.json
47-
48-
49-
* [Manually Install in Arduino Sketchbook]()
50-
* **First** Install the Arduino SAMD Boards through the Arduino Board Manager. This is required for the ARM Cortex-M toolchain.
51-
* Open your Arduno sketchbook folder, listed in Arduino's preferences pane (it is where your libraries folder lives)
52-
* If there is no ```hardware``` folder create it
53-
* Inside the ```hardware``` folder create ```SparkFun```
54-
* Choose to clone with Git or download the .zip of this repo
55-
* Cloning
56-
* Clone this repo into ```SparkFun``` and give it the name ```apollo3```
57-
* .ZIP
58-
* Download the .ZIP of this repository
59-
* Within ```SparkFun``` create the ```apollo3``` directory
60-
* Unzip the contents of the .ZIP into the ```apollo3``` directory
61-
* Restart Arduino IDE for good measure
6264

6365
## How to Contribute
6466
The goal of this Arduino Core is to provide excellent Apollo3 support in a clear and extendable manner. The guidelines for contributing and submitting issues are designed to make it easy to integrate work from many people.

cores/arduino/ard_sup/analog/ap3_analog.cpp

Lines changed: 138 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,13 @@ static const uint8_t outcfg_tbl[32][4] =
107107
{OUTC(1, 4, 1), OUTC(0, 2, 0), OUTC(1, 4, 0), OUTC(1, 1, 1)}, // CTX19: B4OUT2, A2OUT, B4OUT, B1OUT2
108108
{OUTC(0, 5, 0), OUTC(0, 1, 0), OUTC(0, 1, 1), OUTC(1, 2, 1)}, // CTX20: A5OUT, A1OUT, A1OUT2, B2OUT2
109109
{OUTC(0, 5, 1), OUTC(0, 1, 0), OUTC(1, 5, 0), OUTC(0, 0, 1)}, // CTX21: A5OUT2, A1OUT, B5OUT, A0OUT2
110-
//{OUTC(1, 5, 0), OUTC(0, 6, 0), OUTC(0, 1, 0), OUTC(0, 2, 1)}, // CTX22: B5OUT, (error B1OUT) A6OUT, (error remove)A1OUT, A2OUT2
111-
{OUTC(1, 5, 0), OUTC(1, 1, 0), OUTC(0, 6, 0), OUTC(0, 2, 1)}, // CTX22: B5OUT, B1OUT, A6OUT, A2OUT2
110+
{OUTC(1, 5, 0), OUTC(0, 6, 0), OUTC(0, 1, 0), OUTC(0, 2, 1)}, // CTX22: B5OUT, A6OUT, A1OUT, A2OUT2
112111
{OUTC(1, 5, 1), OUTC(0, 7, 0), OUTC(0, 5, 0), OUTC(1, 0, 1)}, // CTX23: B5OUT2, A7OUT, A5OUT, B0OUT2
113112
{OUTC(0, 6, 0), OUTC(0, 2, 0), OUTC(0, 1, 0), OUTC(1, 1, 1)}, // CTX24: A6OUT, A2OUT, A1OUT, B1OUT2
114113
{OUTC(1, 4, 1), OUTC(1, 2, 0), OUTC(0, 6, 0), OUTC(0, 2, 1)}, // CTX25: B4OUT2, B2OUT, A6OUT, A2OUT2
115114
{OUTC(1, 6, 0), OUTC(1, 2, 0), OUTC(0, 5, 0), OUTC(0, 1, 1)}, // CTX26: B6OUT, B2OUT, A5OUT, A1OUT2
116115
{OUTC(1, 6, 1), OUTC(0, 1, 0), OUTC(1, 6, 0), OUTC(1, 2, 1)}, // CTX27: B6OUT2, A1OUT, B6OUT, B2OUT2
117-
{OUTC(0, 7, 1), OUTC(0, 3, 0), OUTC(0, 5, 1), OUTC(1, 0, 1)}, // CTX28: A7OUT(error B?), A3OUT, A5OUT2, B0OUT2
116+
{OUTC(0, 7, 0), OUTC(0, 3, 0), OUTC(0, 5, 1), OUTC(1, 0, 1)}, // CTX28: A7OUT, A3OUT, A5OUT2, B0OUT2
118117
{OUTC(1, 5, 1), OUTC(0, 1, 0), OUTC(0, 7, 0), OUTC(0, 3, 1)}, // CTX29: B5OUT2, A1OUT, A7OUT, A3OUT2
119118
{OUTC(1, 7, 0), OUTC(1, 3, 0), OUTC(0, 4, 1), OUTC(0, 0, 1)}, // CTX30: B7OUT, B3OUT, A4OUT2, A0OUT2
120119
{OUTC(1, 7, 1), OUTC(0, 6, 0), OUTC(1, 7, 0), OUTC(1, 3, 1)}, // CTX31: B7OUT2, A6OUT, B7OUT, B3OUT2
@@ -203,6 +202,34 @@ uint16_t analogRead(uint8_t pinNumber)
203202
}
204203
}
205204

205+
//Power down ADC. Comes from adc_lpmode2.c example from Ambiq SDK
206+
bool power_adc_disable()
207+
{
208+
// Disable the ADC.
209+
if (AM_HAL_STATUS_SUCCESS != am_hal_adc_disable(g_ADCHandle))
210+
{
211+
//am_util_stdio_printf("Error - disable ADC failed.\n");
212+
return (false);
213+
}
214+
215+
// Enable the ADC power domain.
216+
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_periph_disable(AM_HAL_PWRCTRL_PERIPH_ADC))
217+
{
218+
//am_util_stdio_printf("Error - disabling the ADC power domain failed.\n");
219+
return (false);
220+
}
221+
222+
// Deinitialize the ADC
223+
if (AM_HAL_STATUS_SUCCESS != am_hal_adc_deinitialize(g_ADCHandle))
224+
{
225+
//am_util_stdio_printf("Error - return of the ADC instance failed.\n");
226+
return (false);
227+
}
228+
229+
g_ADCHandle = NULL;
230+
return (true);
231+
}
232+
206233
//Apollo3 is capapble of 14-bit ADC but Arduino defaults to 10-bit
207234
//This modifies the global var that controls what is returned from analogRead()
208235
ap3_err_t analogReadResolution(uint8_t bits)
@@ -332,11 +359,87 @@ ap3_err_t ap3_change_channel(uint8_t padNumber)
332359
}
333360
}
334361

362+
void ap3_pwm_wait_for_pulse(uint32_t timer, uint32_t segment, uint32_t output, uint32_t margin)
363+
{
364+
365+
volatile uint32_t *pui32CompareReg;
366+
volatile uint32_t ctimer_val;
367+
uint32_t cmpr0;
368+
369+
// Get the comapre register address
370+
if (segment == AM_HAL_CTIMER_TIMERA)
371+
{
372+
if (output == AM_HAL_CTIMER_OUTPUT_NORMAL)
373+
{
374+
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRA0);
375+
}
376+
else
377+
{
378+
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRAUXA0);
379+
}
380+
}
381+
else
382+
{
383+
if (output == AM_HAL_CTIMER_OUTPUT_NORMAL)
384+
{
385+
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRB0);
386+
}
387+
else
388+
{
389+
pui32CompareReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRAUXB0);
390+
}
391+
}
392+
393+
// Get the compare value
394+
cmpr0 = ((uint32_t)(*(pui32CompareReg)) & 0x0000FFFF);
395+
396+
// Wait for the timer value to be less than the compare value so that it is safe to change
397+
ctimer_val = am_hal_ctimer_read(timer, segment);
398+
while ((ctimer_val + 0) > cmpr0)
399+
{
400+
ctimer_val = am_hal_ctimer_read(timer, segment);
401+
}
402+
}
403+
404+
//**********************************************
405+
// ap3_pwm_output
406+
// - This function allows you to specify an arbitrary pwm output signal with a given frame width (fw) and time high (th).
407+
// - Due to contraints of the hardware th must be lesser than fw by at least 2.
408+
// - Furthermore fw must be at least 3 to see any high pulses
409+
//
410+
// This causes the most significant deviations for small values of fw. For example:
411+
//
412+
// th = 0, fw = 2 --> 0% duty cycle as expected
413+
// th = 1, fw = 2 --> 100% duty cycle --- expected 50%, so 50% error ---
414+
// th = 2, fw = 2 --> 100% duty cycle as expected
415+
//
416+
// th = 0, fw = 3 --> 0% duty cycle as expected
417+
// th = 1, fw = 3 --> 33% duty cycle as expected
418+
// th = 2, fw = 3 --> 100% duty cycle --- expected 66%, so 33% error ---
419+
// th = 3, fw = 3 --> 100% duty cycle as expected
420+
//
421+
// th = 0, fw = 4 --> 0% duty cycle as expected
422+
// th = 1, fw = 4 --> 25% duty cycle as expected
423+
// th = 2, fw = 4 --> 50% duty cycle as expected
424+
// th = 3, fw = 4 --> 100% duty cycle --- expected 75%, so 25% error ---
425+
// th = 4, fw = 4 --> 100% duty cycle as expected
426+
//
427+
// ...
428+
//
429+
// Then we conclude that for the case th == (fw - 1) the duty cycle will be 100% and
430+
// the percent error from the expected duty cycle will be 100/fw
431+
//**********************************************
432+
335433
ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
336434
{
337435
// handle configuration, if necessary
338436
ap3_err_t retval = AP3_OK;
339437

438+
if (fw > 0)
439+
{ // reduce fw so that the user's desired value is the period
440+
fw--;
441+
}
442+
340443
ap3_gpio_pad_t pad = ap3_gpio_pin2pad(pin);
341444
if ((pad == AP3_GPIO_PAD_UNUSED) || (pad >= AP3_GPIO_MAX_PADS))
342445
{
@@ -381,9 +484,7 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
381484
}
382485
}
383486
else
384-
{
385-
const uint8_t n = 0; // use the zeroeth index into the options for any pd except 37 and 39
386-
487+
{ // Use the 0th index of the outcfg_tbl to select the functions
387488
timer = OUTCTIMN(ctx, 0);
388489
if (OUTCTIMB(ctx, 0))
389490
{
@@ -395,6 +496,22 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
395496
}
396497
}
397498

499+
// Ensure that th is not greater than the fw
500+
if (th > fw)
501+
{
502+
th = fw;
503+
}
504+
505+
// Test for AM_HAL_CTIMER_OUTPUT_FORCE0 or AM_HAL_CTIMER_OUTPUT_FORCE1
506+
if ((th == 0) || (fw == 0))
507+
{
508+
output = AM_HAL_CTIMER_OUTPUT_FORCE0;
509+
}
510+
else if (th == fw)
511+
{
512+
output = AM_HAL_CTIMER_OUTPUT_FORCE1;
513+
}
514+
398515
// Configure the pin
399516
am_hal_ctimer_output_config(timer,
400517
segment,
@@ -408,6 +525,9 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
408525
// (AM_HAL_CTIMER_FN_PWM_REPEAT | AP3_ANALOG_CLK | AM_HAL_CTIMER_INT_ENABLE) );
409526
(AM_HAL_CTIMER_FN_PWM_REPEAT | clk));
410527

528+
// Wait until after high pulse to change the state (avoids inversion)
529+
ap3_pwm_wait_for_pulse(timer, segment, output, 10);
530+
411531
// If this pad uses secondary output:
412532
if (output == AM_HAL_CTIMER_OUTPUT_SECONDARY)
413533
{
@@ -434,17 +554,14 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
434554

435555
am_hal_ctimer_start(timer, segment);
436556

437-
// todo: check fw and th -- if they are the same then change the mode to "force output high" to avoid noise
438-
// todo: handle the case where th==0 in a more elegant way (i.e. set mode to "force output low")
439-
440557
return AP3_OK;
441558
}
442559

443560
ap3_err_t analogWriteResolution(uint8_t res)
444561
{
445-
if (res > 15)
562+
if (res > 16)
446563
{
447-
_analogWriteBits = 15; // max out the resolution when this happens
564+
_analogWriteBits = 16; // max out the resolution when this happens
448565
return AP3_ERR;
449566
}
450567
_analogWriteBits = res;
@@ -454,28 +571,25 @@ ap3_err_t analogWriteResolution(uint8_t res)
454571
ap3_err_t analogWrite(uint8_t pin, uint32_t val)
455572
{
456573
// Determine the high time based on input value and the current resolution setting
457-
uint32_t fsv = (0x01 << _analogWriteBits); // full scale value for the current resolution setting
458-
val = val % fsv; // prevent excess
459-
uint32_t clk = AM_HAL_CTIMER_HFRC_12MHZ; // Use an Ambiq HAL provided value to select which clock
460-
//uint32_t fw = 32768; // Choose the frame width in clock periods (32768 -> ~ 350 Hz)
461-
// uint32_t th = (uint32_t)( (fw * val) / fsv );
462-
463-
if (val == 0)
574+
uint32_t fw = 0xFFFF; // Choose the frame width in clock periods (32767 -> ~ 180 Hz)
575+
if (val == ((0x01 << _analogWriteBits) - 1))
464576
{
465-
val = 1; // todo: change this so that when val==0 we set the mode to "force output low"
577+
val = fw; // Enable FORCE1
466578
}
467-
if (val == fsv)
579+
else
468580
{
469-
val -= 1; // todo: change this so that when val==fsv we just set the mode to "force output high"
581+
val <<= (16 - _analogWriteBits); // Shift over the value to fill available resolution
470582
}
471-
return ap3_pwm_output(pin, val, fsv, clk);
583+
uint32_t clk = AM_HAL_CTIMER_HFRC_12MHZ; // Use an Ambiq HAL provided value to select which clock
584+
585+
return ap3_pwm_output(pin, val, fw, clk);
472586
}
473587

474588
ap3_err_t servoWriteResolution(uint8_t res)
475589
{
476-
if (res > 15)
590+
if (res > 16)
477591
{
478-
_servoWriteBits = 15; // max out the resolution when this happens
592+
_servoWriteBits = 16; // max out the resolution when this happens
479593
return AP3_ERR;
480594
}
481595
_servoWriteBits = res;

cores/arduino/ard_sup/ap3_analog.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@ ap3_err_t ap3_set_pin_to_analog(uint8_t pinNumber);
4141
ap3_err_t ap3_analog_pad_funcsel(ap3_gpio_pad_t padNumber, uint8_t *funcsel);
4242
ap3_err_t ap3_change_channel(ap3_gpio_pad_t padNumber);
4343

44+
bool power_adc_disable();
4445
uint16_t analogRead(uint8_t pinNumber);
4546
ap3_err_t analogReadResolution(uint8_t bits);
4647

48+
ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk);
4749
ap3_err_t analogWriteResolution(uint8_t res);
4850
ap3_err_t analogWrite(uint8_t pin, uint32_t val);
4951
ap3_err_t servoWriteResolution(uint8_t res);

cores/arduino/ard_sup/uart/ap3_uart.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,20 @@ void Uart::begin(unsigned long baudrate, am_hal_uart_config_t config)
6767

6868
void Uart::end()
6969
{
70-
// todo:
70+
if (_handle != NULL)
71+
{
72+
flush();
73+
74+
// Power down the UART, and surrender the handle.
75+
am_hal_uart_power_control(_handle, AM_HAL_SYSCTRL_DEEPSLEEP, false);
76+
am_hal_uart_deinitialize(_handle);
77+
78+
// Disable the UART pins.
79+
am_hal_gpio_pinconfig(_pinTX, g_AM_HAL_GPIO_DISABLE);
80+
am_hal_gpio_pinconfig(_pinRX, g_AM_HAL_GPIO_DISABLE);
81+
82+
_handle = NULL;
83+
}
7184
}
7285

7386
int Uart::available()
@@ -93,7 +106,8 @@ int Uart::read()
93106

94107
void Uart::flush()
95108
{
96-
// todo:
109+
// Make sure the UART has finished sending everything it's going to send.
110+
am_hal_uart_tx_flush(_handle);
97111
}
98112

99113
size_t Uart::write(const uint8_t data)

docs/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@ This is a record of the major changes between versions of the SparkFun Arduino A
55

66
Each log entry will use the version number of the release that contains the changes listed. Newest version at the top of the file (just below this line)
77

8+
1.0.1
9+
=====
10+
- Add burst mode support (PR #13)
11+
- Made examples under 'Core Testing' visible through File->Examples menu (PR #10)
12+
- Add EEPROM library (PR #11)
13+
- Fix handling of spaces in paths (PR #20)
14+
- Fix paths to SparkFun SVL for Mac and Linux
15+
- Add ADC power functions and Serial end/flush (PR #18)
16+
817
1.0.0
918
=====
1019
- Add SparkFun Variable Bootloader

0 commit comments

Comments
 (0)