/** ******************************************************************************* * 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" #include "wiring_LL.h" 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; } // the function initializes additional MCU pins depending on the specified pin number void additionalPinsInit(uint32_t PinNumber) { // if we use pin A5, we need to set SELA45 (1.15) to 1 to switch the output from A4 to A5 if (PinNumber == A5) { HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_HIGH); } else if(PinNumber == A4) { // return the switch to A4 in case A5 was previously read HAL_GPIO_PinConfig(GPIO_1, GPIO_PIN_15, HAL_GPIO_MODE_GPIO_OUTPUT, HAL_GPIO_PULL_NONE, HAL_GPIO_DS_2MA); HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_15, GPIO_PIN_LOW); } } // ---------------------- 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_GET_PAD_CONFIG(PORT_0_CFG, pinShift); else config = PIN_GET_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 is stored in ram to improve performance // index = interrupt number. In each row {digitalPinNumber, IntLineValue, IntMuxValue} uint8_t interruptInfo[EXTERNAL_INTERRUPTS_QTY][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) }; int8_t digitalPinToGpioIntMux(uint8_t digPinNumber) { for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptInfo[i][0] == digPinNumber) return interruptInfo[i][2]; } return NOT_AN_INTERRUPT; } int8_t digitalPinToGpioIntLine(uint8_t digPinNumber) { for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; i++) { if (interruptInfo[i][0] == digPinNumber) return interruptInfo[i][1]; } return NOT_AN_INTERRUPT; } int8_t gpioIntLineToInterrupt(uint32_t gpioIntLine) { for (uint8_t i = 0; i < EXTERNAL_INTERRUPTS_QTY; 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_INTERRUPTS_QTY; i++) { if (interruptInfo[i][0] == digPinNumber) return i; } return NOT_AN_INTERRUPT; } // ---------------------- SPI ---------------------- // 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_GET_PAD_CONFIG(PORT_1_CFG, PIN_MASK_TO_PIN_NUMBER(GPIO_PIN_3)); 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)PIN_GET_PAD_CONFIG(PORT_1_PUPD, PIN_MASK_TO_PIN_NUMBER(GPIO_PIN_3)), HAL_GPIO_DS_2MA); HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_4, (GPIO_PinState)GPIO_GET_PIN_STATE(GPIO_1, PIN_MASK_TO_PIN_NUMBER(GPIO_PIN_3))); // 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)PIN_GET_PAD_CONFIG(PORT_1_PUPD, PIN_MASK_TO_PIN_NUMBER(GPIO_PIN_4)), HAL_GPIO_DS_2MA); HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_3, (GPIO_PinState)GPIO_GET_PIN_STATE(GPIO_1, PIN_MASK_TO_PIN_NUMBER(GPIO_PIN_4))); // switch seller back to pin 1.3 HAL_GPIO_WritePin(GPIO_1, GPIO_PIN_6, GPIO_PIN_LOW); spiNssPinIsBlocked = false; // unblock spi pin }