/*------------------------------------------------------------------------------ -- This file is a part of the libuc, microcontroler library -- Copyright (C) 2012, Alexis Jeandet -- -- This program is free software; you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation; either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program; if not, write to the Free Software -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------------- -- Author : Alexis Jeandet -- Mail : alexis.jeandet@member.fsf.org -------------------------------------------------------------------------------*/ #include #include #include #define GPIOGETPORT(gpio) ((GPIO_TypeDef*)(((((uint32_t)gpio) & (uint32_t)0x0000FF00)*(uint32_t)4) + (uint32_t)GPIOA)) #define GPIOPORTNUM(gpio) (((uint32_t)(gpio) & (uint32_t)0x0000FF00)>>(uint32_t)8) gpio_t gpioopen(uint32_t gpio) { gpio &= -1^GPIOSPEEDMASK; gpio |= gpiolowspeed; gpio &= -1^GPIODIRMASK; gpio |= gpioindir; gpio &= -1^GPIOOUTTYPEMASK; gpio |= gpiopushpulltype; gpio &= -1^GPIOPULLTYPEMASK; gpio |= gpionopulltype; gpiosetconfig(&gpio); RCC_AHB1PeriphClockCmd(((uint32_t)0x00000001<OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (i * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_2MHz) << (i * 2)); } } else { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << ((*gpio & 0xFF) * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_2MHz) << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOSPEEDMASK; *gpio |= gpiolowspeed; break; case gpiomediumspeed : if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (i * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_25MHz) << (i * 2)); } } else { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << ((*gpio & 0xFF) * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_25MHz) << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOSPEEDMASK; *gpio |= gpiomediumspeed; break; case gpiofastspeed : if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (i * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_50MHz) << (i * 2)); } } else { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << ((*gpio & 0xFF) * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_50MHz) << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOSPEEDMASK; *gpio |= gpiofastspeed; break; case gpiohighspeed : if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (i * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_100MHz) << (i * 2)); } } else { GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << ((*gpio & 0xFF) * 2)); GPIOx->OSPEEDR |= ((uint32_t)(GPIO_Speed_100MHz) << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOSPEEDMASK; *gpio |= gpiohighspeed; break; } } void gpiosetdir(gpio_t* gpio,gpiodir_t dir) { GPIO_TypeDef* GPIOx = GPIOGETPORT((*gpio)); switch(dir) { case gpiooutdir: if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (i * 2)); GPIOx->MODER |= (GPIO_Mode_OUT << (i * 2)); } } else { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << ((*gpio & 0xFF) * 2)); GPIOx->MODER |= (GPIO_Mode_OUT << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIODIRMASK; *gpio |= gpiooutdir; break; case gpioaf: if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (i * 2)); GPIOx->MODER |= (GPIO_Mode_AF << (i * 2)); } } else { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << ((*gpio & 0xFF) * 2)); GPIOx->MODER |= (GPIO_Mode_AF << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIODIRMASK; *gpio |= gpioaf; break; case gpioan: if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (i * 2)); GPIOx->MODER |= (GPIO_Mode_AN << (i * 2)); } } else { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << ((*gpio & 0xFF) * 2)); GPIOx->MODER |= (GPIO_Mode_AN << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIODIRMASK; *gpio |= gpioan; break; default : if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (i * 2)); GPIOx->MODER |= (GPIO_Mode_IN << (i * 2)); } } else { GPIOx->MODER &= ~(GPIO_MODER_MODER0 << ((*gpio & 0xFF) * 2)); GPIOx->MODER |= (GPIO_Mode_IN << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIODIRMASK; *gpio |= gpioindir; break; } } void gpiosetouttype(gpio_t* gpio, gpioouttype_t outtype) { GPIO_TypeDef* GPIOx = GPIOGETPORT((*gpio)); if(outtype == gpioopendraintype) { if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)i)); GPIOx->OTYPER |= (uint16_t)(GPIO_OType_OD<<((uint16_t)i)); } } else { GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)(*gpio & 0xFF))); GPIOx->OTYPER |= (uint16_t)(GPIO_OType_OD<<((uint16_t)(*gpio & 0xFF))); } *gpio &= ~GPIOOUTTYPEMASK; *gpio |= gpioopendraintype; } else { if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)i)); GPIOx->OTYPER |= (uint16_t)(GPIO_OType_PP<<((uint16_t)i)); } } else { GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)(*gpio & 0xFF))); GPIOx->OTYPER |= (uint16_t)(GPIO_OType_PP<<((uint16_t)(*gpio & 0xFF))); } *gpio &= ~GPIOOUTTYPEMASK; *gpio |= gpiopushpulltype; } } void gpiosetpulltype(gpio_t* gpio,gpiopulltype_t pulltype) { GPIO_TypeDef* GPIOx = GPIOGETPORT(*gpio); switch(pulltype) { case gpiopulluptype: if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)i * 2)); GPIOx->PUPDR |= (GPIO_PuPd_UP << (i * 2)); } } else { GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)(*gpio & 0xFF) * 2)); GPIOx->PUPDR |= (GPIO_PuPd_UP << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOPULLTYPEMASK; *gpio |= gpiopulluptype; break; case gpiopulldowntype: if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)i * 2)); GPIOx->PUPDR |= (GPIO_PuPd_DOWN << (i * 2)); } } else { GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)(*gpio & 0xFF) * 2)); GPIOx->PUPDR |= (GPIO_PuPd_DOWN << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOPULLTYPEMASK; *gpio |= gpiopulldowntype; break; default : if((*gpio & 0xFF)==0xFF) { for(int i=0;i<16;i++) { GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)i * 2)); GPIOx->PUPDR |= (GPIO_PuPd_NOPULL << (i * 2)); } } else { GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)(*gpio & 0xFF) * 2)); GPIOx->PUPDR |= (GPIO_PuPd_NOPULL << ((*gpio & 0xFF) * 2)); } *gpio &= ~GPIOPULLTYPEMASK; *gpio |= gpionopulltype; break; } } void gpioset(gpio_t gpio) { GPIO_TypeDef* GPIOx = GPIOGETPORT(gpio); if((gpio & 0xFF)==0xFF) { GPIOx->BSRRL = -1; } else { GPIOx->BSRRL = 1<<(gpio & 0xFF); } } void gpioclr(gpio_t gpio) { GPIO_TypeDef* GPIOx = GPIOGETPORT(gpio); if((gpio & 0xFF)==0xFF) { GPIOx->BSRRH = -1; } else { GPIOx->BSRRH = 1<<(gpio & 0xFF); } } void gpiosetval(gpio_t gpio,int val) { GPIO_TypeDef* GPIOx = GPIOGETPORT(gpio); if((gpio & 0xFF)==0xFF) { GPIOx->ODR = val; } else { if(val) GPIOx->BSRRL = 1<<(gpio & 0xFF); else GPIOx->BSRRH = 1<<(gpio & 0xFF); } } int gpiogetval(gpio_t gpio) { GPIO_TypeDef* GPIOx = GPIOGETPORT(gpio); if((gpio & 0xFF)==0xFF) { return GPIOx->IDR; } else { return ((GPIOx->IDR>>(gpio & 0xFF)) & 1); } }