Skip to content

Release #163

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

Merged
merged 12 commits into from
May 6, 2020
124 changes: 83 additions & 41 deletions cores/arduino/ard_sup/analog/ap3_analog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,15 +121,16 @@ static const uint8_t outcfg_tbl[32][4] =

#define AP3_MAX_ANALOG_WRITE_WIDTH 0x0000FFFF

uint16_t _analogBits = 10; //10-bit by default
uint8_t _analogWriteBits = 8; // 8-bit by default for writes
uint8_t _servoWriteBits = 8; // 8-bit by default for writes
uint16_t _analogBits = 10; //10-bit by default
uint8_t _analogWriteBits = 8; // 8-bit by default for writes
uint8_t _servoWriteBits = 8; // 8-bit by default for writes
static bool ap3_adc_initialized = false; // flag to show if the ADC has been initialized
static uint32_t _analogWriteWidth = 0x0000FFFF;

uint16_t analogRead(uint8_t pinNumber)
{
if(!ap3_adc_initialized){
if (!ap3_adc_initialized)
{
ap3_adc_setup();
ap3_adc_initialized = true;
}
Expand Down Expand Up @@ -222,6 +223,35 @@ uint16_t analogRead(uint8_t pinNumber)
}
}

//Returns the internal temperature of the Apollo3
float getInternalTemp()
{
const float fReferenceVoltage = 2.0;
float fADCTempDegreesC = 0.0;

uint16_t internalTemp = analogRead(ADC_INTERNAL_TEMP); //Read internal temp sensor channel

//
// Convert and scale the temperature.
// Temperatures are in Fahrenheit range -40 to 225 degrees.
// Voltage range is 0.825V to 1.283V
// First get the ADC voltage corresponding to temperature.
//
float fADCTempVolts = ((float)internalTemp) * fReferenceVoltage / ((float)(pow(2, _analogBits)));

float fVT[3];
fVT[0] = fADCTempVolts;
fVT[1] = 0.0f;
fVT[2] = -123.456;
uint32_t ui32Retval = am_hal_adc_control(g_ADCHandle, AM_HAL_ADC_REQ_TEMP_CELSIUS_GET, fVT);
if (ui32Retval == AM_HAL_STATUS_SUCCESS)
{
fADCTempDegreesC = fVT[1]; // Get the temperature
}

return (fADCTempDegreesC);
}

//Power down ADC. Comes from adc_lpmode2.c example from Ambiq SDK
bool power_adc_disable()
{
Expand Down Expand Up @@ -508,19 +538,21 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)

// if timer is running wait for timer value to roll over (will indicate that at least one pulse has been emitted)
AM_CRITICAL_BEGIN // critical section when reading / writing config registers
if(*((uint32_t*)CTIMERADDRn(CTIMER, timer, CTRL0)) & (CTIMER_CTRL0_TMRA0EN_Msk | CTIMER_CTRL0_TMRB0EN_Msk)){
if (*((uint32_t *)CTIMERADDRn(CTIMER, timer, CTRL0)) & (CTIMER_CTRL0_TMRA0EN_Msk | CTIMER_CTRL0_TMRB0EN_Msk))
{
uint32_t current = 0;
uint32_t last = 0;
do {
do
{
last = current;
current = am_hal_ctimer_read( timer, segment);
}while(current >= last);
current = am_hal_ctimer_read(timer, segment);
} while (current >= last);
}

AM_CRITICAL_END // end critical section

// clear timer (also stops the timer)
am_hal_ctimer_clear(timer, segment);
// clear timer (also stops the timer)
am_hal_ctimer_clear(timer, segment);

// Configure the repeated pulse mode with our clock source
am_hal_ctimer_config_single(timer,
Expand All @@ -538,25 +570,27 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
pui32ConfigReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, AUX0);
uint32_t ui32WriteVal = AM_REGVAL(pui32ConfigReg);
uint32_t ui32ConfigVal = (1 << CTIMER_AUX0_TMRA0EN23_Pos); // using CTIMER_AUX0_TMRA0EN23_Pos because for now this number is common to all CTimer instances
volatile uint32_t *pui32CompareRegA = (uint32_t*)CTIMERADDRn(CTIMER, timer, CMPRA0);
volatile uint32_t *pui32CompareRegB = (uint32_t*)CTIMERADDRn(CTIMER, timer, CMPRB0);
uint32_t masterPeriod = (uint32_t)(*(pui32CompareRegA) & CTIMER_CMPRA0_CMPR1A0_Msk) >> CTIMER_CMPRA0_CMPR1A0_Pos;
uint32_t masterRisingTrigger = (uint32_t)(*(pui32CompareRegA) & CTIMER_CMPRA0_CMPR0A0_Msk) >> CTIMER_CMPRA0_CMPR0A0_Pos;
volatile uint32_t *pui32CompareRegA = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRA0);
volatile uint32_t *pui32CompareRegB = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRB0);
uint32_t masterPeriod = (uint32_t)(*(pui32CompareRegA)&CTIMER_CMPRA0_CMPR1A0_Msk) >> CTIMER_CMPRA0_CMPR1A0_Pos;
uint32_t masterRisingTrigger = (uint32_t)(*(pui32CompareRegA)&CTIMER_CMPRA0_CMPR0A0_Msk) >> CTIMER_CMPRA0_CMPR0A0_Pos;

if (segment == AM_HAL_CTIMER_TIMERB)
{
ui32ConfigVal = ((ui32ConfigVal & 0xFFFF) << 16);
masterPeriod = (uint32_t)(*(pui32CompareRegB) & CTIMER_CMPRB0_CMPR1B0_Msk) >> CTIMER_CMPRB0_CMPR1B0_Pos;
masterRisingTrigger = (uint32_t)(*(pui32CompareRegA) & CTIMER_CMPRB0_CMPR0B0_Msk) >> CTIMER_CMPRB0_CMPR0B0_Pos;
masterPeriod = (uint32_t)(*(pui32CompareRegB)&CTIMER_CMPRB0_CMPR1B0_Msk) >> CTIMER_CMPRB0_CMPR1B0_Pos;
masterRisingTrigger = (uint32_t)(*(pui32CompareRegA)&CTIMER_CMPRB0_CMPR0B0_Msk) >> CTIMER_CMPRB0_CMPR0B0_Pos;
}
ui32WriteVal |= ui32ConfigVal;
AM_REGVAL(pui32ConfigReg) = ui32WriteVal;

if(masterPeriod != fw){
if (masterPeriod != fw)
{
// the master output fw dictates the secondary fw... so if they are different try to change the master while preserving duty cycle
uint32_t masterTH = ((masterPeriod - masterRisingTrigger) * fw) / masterPeriod; // try to compensate in case _analogWriteWidth was changed
if(masterPeriod == 0){ // if masterPeriod was 0 then masterTH will be invalid (divide by 0). This usually means that the master timer output did not have a set duty cycle. This also means the output is probably not configured and so it is okay to choose an arbitrary duty cycle
masterTH = fw - 1;
if (masterPeriod == 0)
{ // if masterPeriod was 0 then masterTH will be invalid (divide by 0). This usually means that the master timer output did not have a set duty cycle. This also means the output is probably not configured and so it is okay to choose an arbitrary duty cycle
masterTH = fw - 1;
}
am_hal_ctimer_period_set(timer, segment, fw, masterTH); // but this overwrites the non-aux compare regs for this timer / segment
// Serial.printf("th = %d, fw = %d, (masterPeriod - masterRisingTrigger) = (%d - %d) = %d\n", th, fw, masterPeriod, masterRisingTrigger, (masterPeriod - masterRisingTrigger));
Expand All @@ -570,25 +604,28 @@ ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk)
// Try to preserve settings of the secondary output
uint32_t *pui32ConfigReg = NULL;
pui32ConfigReg = (uint32_t *)CTIMERADDRn(CTIMER, timer, AUX0);
volatile uint32_t *pui32CompareRegA = (uint32_t*)CTIMERADDRn(CTIMER, timer, CMPRAUXA0);
volatile uint32_t *pui32CompareRegB = (uint32_t*)CTIMERADDRn(CTIMER, timer, CMPRAUXB0);
uint32_t slavePeriod = (uint32_t)(*(pui32CompareRegA) & CTIMER_CMPRA0_CMPR1A0_Msk) >> CTIMER_CMPRA0_CMPR1A0_Pos;
uint32_t slaveRisingTrigger = (uint32_t)(*(pui32CompareRegA) & CTIMER_CMPRA0_CMPR0A0_Msk) >> CTIMER_CMPRA0_CMPR0A0_Pos;
volatile uint32_t *pui32CompareRegA = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRAUXA0);
volatile uint32_t *pui32CompareRegB = (uint32_t *)CTIMERADDRn(CTIMER, timer, CMPRAUXB0);
uint32_t slavePeriod = (uint32_t)(*(pui32CompareRegA)&CTIMER_CMPRA0_CMPR1A0_Msk) >> CTIMER_CMPRA0_CMPR1A0_Pos;
uint32_t slaveRisingTrigger = (uint32_t)(*(pui32CompareRegA)&CTIMER_CMPRA0_CMPR0A0_Msk) >> CTIMER_CMPRA0_CMPR0A0_Pos;

uint32_t auxEnabled = (AM_REGVAL(pui32ConfigReg) & CTIMER_AUX0_TMRA0EN23_Msk);

if (segment == AM_HAL_CTIMER_TIMERB)
{
auxEnabled = (AM_REGVAL(pui32ConfigReg) & (CTIMER_AUX0_TMRA0EN23_Msk << 16));
slavePeriod = (uint32_t)(*(pui32CompareRegB) & CTIMER_CMPRB0_CMPR1B0_Msk) >> CTIMER_CMPRB0_CMPR1B0_Pos;
slaveRisingTrigger = (uint32_t)(*(pui32CompareRegA) & CTIMER_CMPRB0_CMPR0B0_Msk) >> CTIMER_CMPRB0_CMPR0B0_Pos;
slavePeriod = (uint32_t)(*(pui32CompareRegB)&CTIMER_CMPRB0_CMPR1B0_Msk) >> CTIMER_CMPRB0_CMPR1B0_Pos;
slaveRisingTrigger = (uint32_t)(*(pui32CompareRegA)&CTIMER_CMPRB0_CMPR0B0_Msk) >> CTIMER_CMPRB0_CMPR0B0_Pos;
}

if( auxEnabled ){ // if secondary outputs are enabled
if( slavePeriod != fw ){ // and if fw is different from previous slavePeriod
if (auxEnabled)
{ // if secondary outputs are enabled
if (slavePeriod != fw)
{ // and if fw is different from previous slavePeriod
uint32_t slaveTH = ((slavePeriod - slaveRisingTrigger) * fw) / slavePeriod; // try to compensate in case _analogWriteWidth was changed
if(slavePeriod == 0){ // if masterPeriod was 0 then masterTH will be invalid (divide by 0). This usually means that the master timer output did not have a set duty cycle. This also means the output is probably not configured and so it is okay to choose an arbitrary duty cycle
slaveTH = fw - 1;
if (slavePeriod == 0)
{ // if masterPeriod was 0 then masterTH will be invalid (divide by 0). This usually means that the master timer output did not have a set duty cycle. This also means the output is probably not configured and so it is okay to choose an arbitrary duty cycle
slaveTH = fw - 1;
}
am_hal_ctimer_aux_period_set(timer, segment, fw, slaveTH); // but this overwrites the non-aux compare regs for this timer / segment
}
Expand All @@ -615,20 +652,25 @@ ap3_err_t analogWriteResolution(uint8_t res)
return AP3_OK;
}

ap3_err_t analogWriteFrameWidth(uint32_t fw){
ap3_err_t analogWriteFrameWidth(uint32_t fw)
{
_analogWriteWidth = fw;
if(_analogWriteWidth > AP3_MAX_ANALOG_WRITE_WIDTH){
if (_analogWriteWidth > AP3_MAX_ANALOG_WRITE_WIDTH)
{
_analogWriteWidth = AP3_MAX_ANALOG_WRITE_WIDTH;
}
return AP3_OK;
}

ap3_err_t analogWriteFrequency(float freq){
ap3_err_t analogWriteFrequency(float freq)
{
_analogWriteWidth = (uint32_t)(12000000 / freq);
if(_analogWriteWidth > AP3_MAX_ANALOG_WRITE_WIDTH){
if (_analogWriteWidth > AP3_MAX_ANALOG_WRITE_WIDTH)
{
return AP3_ERR;
}
if(_analogWriteWidth < 3){
if (_analogWriteWidth < 3)
{
return AP3_ERR;
}
return AP3_OK;
Expand All @@ -655,12 +697,12 @@ ap3_err_t servoWriteResolution(uint8_t res)

uint8_t getServoResolution()
{
return(_servoWriteBits);
return (_servoWriteBits);
}

ap3_err_t servoWrite(uint8_t pin, uint32_t val)
{
return(servoWrite(pin, val, 544, 2400)); //Call servoWrite with Arduino default min/max microseconds. See: https://www.arduino.cc/en/Reference/ServoAttach
return (servoWrite(pin, val, 544, 2400)); //Call servoWrite with Arduino default min/max microseconds. See: https://www.arduino.cc/en/Reference/ServoAttach
}

ap3_err_t servoWrite(uint8_t pin, uint32_t val, uint16_t minMicros, uint16_t maxMicros)
Expand All @@ -672,9 +714,9 @@ ap3_err_t servoWrite(uint8_t pin, uint32_t val, uint16_t minMicros, uint16_t max
uint32_t fw = 60000; // 20 ms wide frame

//Convert microSeconds to PWM counts.
uint32_t min = minMicros * 3;
uint32_t min = minMicros * 3;
uint32_t max = maxMicros * 3;

uint32_t th = (uint32_t)(((max - min) * val) / fsv) + min;

return ap3_pwm_output(pin, th, fw, clk);
Expand Down
1 change: 1 addition & 0 deletions cores/arduino/ard_sup/ap3_analog.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ ap3_err_t ap3_change_channel(ap3_gpio_pad_t padNumber);
bool power_adc_disable();
uint16_t analogRead(uint8_t pinNumber);
ap3_err_t analogReadResolution(uint8_t bits);
float getInternalTemp();

ap3_err_t ap3_pwm_output(uint8_t pin, uint32_t th, uint32_t fw, uint32_t clk);
ap3_err_t analogWriteResolution(uint8_t res);
Expand Down
1 change: 1 addition & 0 deletions cores/arduino/ard_sup/gpio/ap3_gpio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ extern void detachInterrupt(uint8_t pin)
gpio_isr_entries[gpio_num_isr].callback = NULL;
gpio_isr_entries[gpio_num_isr].mode = LOW;
gpio_isr_entries[gpio_num_isr].arg = NULL;
gpio_num_isr--;
}

uint32_t ap3_gpio_enable_interrupts(uint32_t ui32Pin, uint32_t eIntDir)
Expand Down
5 changes: 4 additions & 1 deletion libraries/Examples/examples/Advanced/LowPower/LowPower.ino
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ void setup()
// These two GPIOs are critical: the TX/RX connections between the Artemis module and the CH340S on the Blackboard
// are prone to backfeeding each other. To stop this from happening, we must reconfigure those pins as GPIOs
// and then disable them completely:
Serial.println("The TX and RX pins need to be disabled to minimize the current draw.");
Serial.println("You should not see any more Serial messages after this...");
delay(100);
am_hal_gpio_pinconfig(48 /* TXO-0 */, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(49 /* RXI-0 */, g_AM_HAL_GPIO_DISABLE);

Expand Down Expand Up @@ -104,4 +107,4 @@ void setup()
void loop()
{
//Do nothing
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ void setup()
// These two GPIOs are critical: the TX/RX connections between the Artemis module and the CH340S on the Blackboard
// are prone to backfeeding each other. To stop this from happening, we must reconfigure those pins as GPIOs
// and then disable them completely:
Serial.println("The TX and RX pins need to be disabled to minimize the current draw.");
Serial.println("You should not see any more Serial messages after this...");
delay(100);
am_hal_gpio_pinconfig(48 /* TXO-0 */, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(49 /* RXI-0 */, g_AM_HAL_GPIO_DISABLE);

Expand Down Expand Up @@ -140,4 +143,4 @@ extern "C" void am_rtc_isr(void)
delay(100);
digitalWrite(LED_BUILTIN, LOW);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,8 @@ void loop()
Serial.print(vcc, 2);
Serial.print("V");

int internalTempVoltage = analogRead(ADC_INTERNAL_TEMP); //Read internal temp sensor. 3.8mV/C, +/-3C
double internalTemp = internalTempVoltage * vcc / 16384.0; //Convert internal temp reading to voltage
internalTemp /= 0.0038; //Convert voltage to degrees C
Serial.print("\tinternalTemp: ");
Serial.print(internalTemp, 2);
Serial.print(getInternalTemp(), 2);

int vss = analogRead(ADC_INTERNAL_VSS); //Read internal VSS (should be 0)
Serial.print("\tvss: ");
Expand Down
5 changes: 2 additions & 3 deletions platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ defines.variant={build.defs}


## Compiler and Toolchain
compiler.path={runtime.tools.arm-none-eabi-gcc-8-2018-q4-major.path}/bin
compiler.path={runtime.tools.arm-none-eabi-gcc-7-2017q4.path}/bin
compiler.cmd.cpp=arm-none-eabi-g++
compiler.cmd.c=arm-none-eabi-gcc
compiler.cmd.S=arm-none-eabi-gcc
Expand Down Expand Up @@ -118,8 +118,7 @@ recipe.objcopy.bin.pattern="{compiler.path}/{compiler.cmd.axf2bin}" {compiler.fl
## Compute size
recipe.size.pattern="{compiler.path}/{compiler.cmd.size}" -A "{build.path}/{build.project_name}.axf"
recipe.size.regex=\.text\s+([0-9]+).*

recipe.hooks.objcopy.postobjcopy.0.pattern="{compiler.path}/{compiler.cmd.size}" -A "{build.path}/{build.project_name}.axf"
recipe.size.regex.data=^(?:\.data|\.bss)\s+([0-9]+).*

## Preprocessor
preproc.macros.flags=-w -x c++ -E -CC
Expand Down