elbear_arduino_bsp/variants/standart/variant.c

313 lines
9.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
*******************************************************************************
* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
* All rights reserved.
*
* This software component is licensed by WCH under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
*******************************************************************************
*/
#include "pins_arduino.h"
#include "mik32_hal_adc.h"
#include "wiring_analog.h"
#ifdef __cplusplus
extern "C" {
#endif
void ErrorMsgHandler(const char * msg);
#ifdef __cplusplus
}
#endif
bool spiNssPinIsBlocked = false;
// list of pin numbers from both ports with pins inside the port
const HAL_PinsTypeDef digitalPinToGpioPinArray[] =
{
GPIO_PIN_5, // D0
GPIO_PIN_6, // D1
GPIO_PIN_10,// D2
GPIO_PIN_0, // D3
GPIO_PIN_8, // D4
GPIO_PIN_1, // D5
GPIO_PIN_2, // D6
GPIO_PIN_8, // D7
GPIO_PIN_9, // D8
GPIO_PIN_3, // D9
GPIO_PIN_3, // D10
GPIO_PIN_1, // D11
GPIO_PIN_0, // D12
GPIO_PIN_2, // D13
GPIO_PIN_5, // D14/A0
GPIO_PIN_7, // D15/A1
GPIO_PIN_4, // D16/A2
GPIO_PIN_7, // D17/A3
GPIO_PIN_12,// D18
GPIO_PIN_13,// D19
GPIO_PIN_9, // A4 (board pin 20)
GPIO_PIN_9, // A5 (board pin 21)
GPIO_PIN_7, // LED(pin 22)
GPIO_PIN_6 // BTN(pin 23)
};
// etermines the address of the port by the board pin number to which this pin belongs on the MCU
GPIO_TypeDef* digitalPinToPort(uint32_t digPinNumber)
{
GPIO_TypeDef* gpioNum = 0;
// port 0 - board pins 0...6, 9, 16(A2), 17(A3), 20(A4), 21(A5)
if ((digPinNumber >= 0 && digPinNumber <= 6) || digPinNumber == 9 || digPinNumber == 16
|| digPinNumber == 17 || digPinNumber == 20 || digPinNumber == 21) // 12 pieces
gpioNum = GPIO_0;
// port 1 - board pins 7, 8, 10...13, 14(А0), 15(А1), 18,19
else if (digPinNumber == 7 || digPinNumber == 8 || (digPinNumber >= 10 && digPinNumber <= 15)
|| digPinNumber == 18 || digPinNumber == 19) // 10 pieces
gpioNum = GPIO_1;
// port 2 - led and button
else if (digPinNumber == LED_BUILTIN || digPinNumber == BTN_BUILTIN)
gpioNum = GPIO_2;
return gpioNum;
}
// determines the pin address inside the port by the board pin number
HAL_PinsTypeDef digitalPinToBitMask(uint32_t digPinNumber)
{
if (digPinNumber < pinCommonQty())
{
HAL_PinsTypeDef mask;
// if spi is on default pin 1.3 is needed for spi, D10 is replaced to pin 1.4
if (spiNssPinIsBlocked && (digPinNumber == 10))
mask = GPIO_PIN_4;
else
mask = digitalPinToGpioPinArray[digPinNumber];
return mask;
}
else
return NC;
}
uint16_t pinCommonQty(void)
{
return (uint16_t)(sizeof(digitalPinToGpioPinArray)/sizeof(digitalPinToGpioPinArray[0]));
}
// the function returns a reference to the OUTPUT address of the GPIO register
volatile uint32_t* portOutputRegister(GPIO_TypeDef* GPIO_x)
{
return &GPIO_x->OUTPUT_;
}
// the function returns a reference to the STATE address of the GPIO register
volatile uint32_t* portInputRegister(GPIO_TypeDef* GPIO_x)
{
return &GPIO_x->STATE;
}
// return config of pin with pinShift(0...16) in portReg (config, pupd, ds for ports 0...2)
#define PIN_PAD_CONFIG(portReg, pinShift) ((PAD_CONFIG->portReg >> (pinShift<<1)) & 0b11)
// ---------------------- ADC ---------------------- //
// determines the ADC channel number by the board pin number
uint32_t analogInputToChannelNumber(uint32_t PinNumber)
{
uint32_t adcChannel = 0;
// if get a value 0...5 instead of A0...A5
if (PinNumber < 4) PinNumber += 14;
else if (PinNumber < 6) PinNumber += 16;
switch (PinNumber)
{
case PIN_A0:
adcChannel = ADC_CHANNEL0;
break;
case PIN_A1:
adcChannel = ADC_CHANNEL1;
break;
case PIN_A2:
adcChannel = ADC_CHANNEL3;
break;
case PIN_A3:
adcChannel = ADC_CHANNEL4;
break;
case PIN_A4:
case PIN_A5:
adcChannel = ADC_CHANNEL5;
break;
default:
adcChannel = NC;
}
return adcChannel;
}
// ---------------------- PWM ---------------------- //
// use only if digitalPinHasPWM() == true
#define PWM_PIN_TO_PORT_NUMBER(pin) (((pin==10)||(pin==11)) ? 1:0)
// use only if digitalPinHasPWM() == true
static inline uint8_t pwmPinToGpioPinShift(uint8_t digitalPin)
{
if (digitalPin == 3)
return 0;
else if ((digitalPin == 5) || (digitalPin == 11))
return 1;
else if (digitalPin == 6)
return 2;
else // pins 9 10
return 3;
}
// use only if digitalPinHasPWM() == true
// return true if digitalPin configured as pwm
bool digitalPinPwmIsOn(uint8_t digitalPin)
{
uint8_t config = 0;
uint8_t pinShift = pwmPinToGpioPinShift(digitalPin);
if (PWM_PIN_TO_PORT_NUMBER(digitalPin) == 0)
config = PIN_PAD_CONFIG(PORT_0_CFG, pinShift);
else
config = PIN_PAD_CONFIG(PORT_1_CFG, pinShift);
if (config == 2)
return true;
else
return false;
}
bool digitalPinHasPWM(uint8_t p)
{
bool ret = false;
// if spi is in use D10 cannot work as pwm
if (spiNssPinIsBlocked && (p == 10))
ret = false;
else if ((p) == 3 || (p) == 5 || (p) == 6 || (p) == 9 || (p) == 10 || (p) == 11)
ret = true;
return ret;
}
// function is used only if digitalPinHasPWM() is true
TIMER32_TypeDef* pwmPinToTimer(uint32_t digPinNumber)
{
TIMER32_TypeDef* timerNum = NULL;
// timer 1
if (digPinNumber == 3 || digPinNumber == 5 || digPinNumber == 6 || digPinNumber == 9)
timerNum = TIMER32_1;
// timer 2
else if (digPinNumber == 10 || digPinNumber == 11)
timerNum = TIMER32_2;
return timerNum;
}
// function is used only if digitalPinHasPWM() is true
HAL_TIMER32_CHANNEL_IndexTypeDef pwmPinToTimerChannel(uint32_t digPinNumber)
{
HAL_TIMER32_CHANNEL_IndexTypeDef channel = 0;
if (digPinNumber == 3) channel = TIMER32_CHANNEL_0;
else if (digPinNumber == 5 || digPinNumber == 11) channel = TIMER32_CHANNEL_1;
else if (digPinNumber == 6) channel = TIMER32_CHANNEL_2;
else if (digPinNumber == 9 || digPinNumber == 10) channel = TIMER32_CHANNEL_3;
return channel;
}
// ---------------------- interrupts ---------------------- //
// interrupt table
// index = interrupt number. In each row {digitalPinNumber, IntLineValue, IntMuxValue}
const uint8_t interruptInfo[EXTERNAL_NUM_INTERRUPTS][3] =
{
{ 2, GPIO_LINE_2, GPIO_MUX_LINE_2_PORT0_10}, // INT0
{ 3, GPIO_LINE_0, GPIO_MUX_LINE_0_PORT0_0}, // INT1
{ 4, GPIO_LINE_4, GPIO_MUX_LINE_4_PORT0_8}, // INT2
{ 5, GPIO_LINE_1, GPIO_MUX_LINE_1_PORT0_1}, // INT3
{ 8, GPIO_LINE_5, GPIO_MUX_LINE_5_PORT1_9}, // INT4
{ 9, GPIO_LINE_3, GPIO_MUX_LINE_3_PORT0_3}, // INT5
{BTN_BUILTIN, GPIO_LINE_6, GPIO_MUX_LINE_6_PORT2_6}, // INT6 (button)
};
uint32_t interruptToDigitalPin(uint8_t interruptNum)
{
return interruptInfo[interruptNum][0];
}
uint32_t interruptToGpioIntLine(uint8_t interruptNum)
{
return (uint32_t)interruptInfo[interruptNum][1];
}
uint32_t interruptToGpioIntMux(uint8_t interruptNum)
{
return (uint32_t)interruptInfo[interruptNum][2];
}
int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine)
{
for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++)
{
if (interruptInfo[i][1] == gpioIntLine)
return i;
}
return NOT_AN_INTERRUPT;
}
int8_t digitalPinToInterrupt(uint32_t digPinNumber)
{
for (uint8_t i = 0; i < EXTERNAL_NUM_INTERRUPTS; i++)
{
if (interruptInfo[i][0] == digPinNumber)
return i;
}
return NOT_AN_INTERRUPT;
}
// ---------------------- SPI ---------------------- //
// pins shift in registers
#define PIN_3_SHIFT 3
#define PIN_4_SHIFT 4
#define PORT1_GET_PAD_PUPD(pinShift) ((PAD_CONFIG->PORT_1_PUPD >> (pinShift<<1)) & 0b11)
#define PORT1_GET_GPIO_STATE(pinShift) ((GPIO_1->OUTPUT_ >> pinShift) & 0b1)
void spi_onBegin(void)
{
// On Elbear Ace-Uno rev1.1.0 there is a seller on pin 1.6 which replace D10 from spi NSS pin 1.3 to pin 1.4,
// because spi needs pin 1.3 for correct work
// replace config from 1.3 to 1.4
uint8_t config = PIN_PAD_CONFIG(PORT_1_CFG, PIN_3_SHIFT);
if (config == 0) // common gpio
{
// get info from pin gpio1.3 and set config to gpio1.4
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_4, HAL_GPIO_GetPinDirection(GPIO_1, GPIO_PIN_3),
(HAL_GPIO_PullTypeDef)PORT1_GET_PAD_PUPD(PIN_3_SHIFT), HAL_GPIO_DS_2MA);
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_4, (GPIO_PinState)PORT1_GET_GPIO_STATE(PIN_3_SHIFT));
// pin D10 was switched to different gpio and can be used further
}
else if(config == 2) // timer for pwm
{
// if D10 (spi NSS pin) was used as pwm, we need to stop timer, because 1.4 don't support it
analogWriteStop(10);
ErrorMsgHandler("analogWrite(): D10 cannot be used as PWM pin while SPI is running");
}
// switch seller to pin 1.4
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_6, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA);
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_HIGH);
spiNssPinIsBlocked = true; // block spi pin
}
void spi_onEnd(void)
{
// get info from pin gpio1.4 and set config to gpio1.3
HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_3, HAL_GPIO_GetPinDirection(GPIO_1, GPIO_PIN_4),
(HAL_GPIO_PullTypeDef)PORT1_GET_PAD_PUPD(PIN_4_SHIFT), HAL_GPIO_DS_2MA);
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_3, (GPIO_PinState)PORT1_GET_GPIO_STATE(PIN_4_SHIFT));
// switch seller back to pin 1.3
HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_LOW);
spiNssPinIsBlocked = false; // unblock spi pin
}