text: /**
   ******************************************************************************
   * @file           : main.c
   * @author         : Joao Nuno Carvalho and parts Auto-generated by STM32CubeIDE
   * @brief          : Main program body
   ******************************************************************************
   * Description     : This little project makes a LED blink and sends a message
   *                   to the debug SWv trace line when a button is pressed.
   *                   But what is kind of neat is that it does that without any
   *                   use of previously configured STM32F407GV files for the
   *                   registers.
   *                   I went to the datasheet and the reference manual of the
   *                   microcontroller STM32F407GV of the board STM32F407
   *                   DISCOVERY KIT version DISC1, and using the memory map data
   *                   of the datasheet and the reference manual register offset's
   *                   mapped each register (variable) into memory (BASE_ADDRESS +
   *                   OFFSET) and from there programmed this little program using
   *                   direct register programming.
   *                   Of course this is a simple thing but a neat example of
   *                   how to do it.
   *                   I also made reg_base_addresses.h, that as all memory maps
   *                   defined, for more serious uses, use the 15K lines file from
   *                   STM32 for this processor that is more complete and as all
   *                   the registers already mapped.
   *
   * @attention
   *
   * This software component is licensed by ST 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
   *
   ******************************************************************************
   */
  
  #if !defined(__SOFT_FP__) && defined(__ARM_FP)
    #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use."
  #endif
  
  #include <stdio.h>
  #include <stdint.h>
  #include "reg_base_addresses.h"
  
  // Enable the clock of the peripherals GPIOD e GPIOA in the register RCC.
  #define RCC_BASE_ADDR          0x40023800UL
  #define RCC_AHB1_ENR_OFFSET    0x30UL
  #define RCC_AHB1_ENR_ADDR      (RCC_BASE_ADDR + RCC_AHB1_ENR_OFFSET)
  
  // Green LED - pin PD12 OUTPUT   BUS AHB1.
  #define GPIOD_BASE_ADDR        0x40020C00UL
  
  #define GPIOx_MODER_OFFSET     0x00UL
  #define GPIOD_MODER_ADDR       (GPIOD_BASE_ADDR + GPIOx_MODER_OFFSET)
  
  // Button USER pin PA0 Input   BUS AHB1.
  #define GPIOA_BASE_ADDR        0x40020000UL
  #define GPIOA_MODER_ADDR       (GPIOA_BASE_ADDR + GPIOx_MODER_OFFSET)
  
  #define GPIOx_MODER_RESET_VALUE 0xA8000000UL
  
  // LED pin data Output GPIOD.
  #define GPIOx_ODR_OFFSET       0x14UL
  #define GPIOD_ODR_ADDR         (GPIOD_BASE_ADDR + GPIOx_ODR_OFFSET)
  
  // Button pin data Input GPIOA.
  #define GPIOx_IDR_OFFSET       0x10UL
  #define GPIOA_IDR_ADDR         (GPIOA_BASE_ADDR + GPIOx_IDR_OFFSET)
  
  
  #define DELAY_SEC           0.2
  #define ONE_SECOND          4000000
  
  
  void delay(int maxTime){
  	int volatile dummy = 0;
  	for(int i=0; i < maxTime; i++){
  		dummy++;
  	}
  }
  
  int getButtonState(){
  	uint32_t volatile *pGpioAIdr = (uint32_t *) GPIOA_IDR_ADDR;
  
  	int buttonVal = 0;
  	// Button read value.
  	if (*pGpioAIdr & (1 << 0))
  	{
  		// Button High
  		buttonVal = 1;
  	}
  	else
  	{
  		buttonVal = 0;
  	}
  	return buttonVal;
  }
  
  int main(void)
  {
  	int a = 1;
  	int b = 1;
  	int c = 0;
  
  	c = a + b;
  	printf("Hello world: %d.\n", c);
  
  	/*
  	 To put a LED blinking.
  	 Green LED pin PD12 OUTPUT.  (normally is at zero and becomes active at one [High]).
  	 1. Ativate the GPIO clock on RCC register.
  	 2. Config the GPIO do LED pin as an output pin in the register MODE.
  	 3. LOOP
  	  	  3.1 Write 0 (zero) to the bit of the data register ODR.
  	  	  3.2 Delay (500ms)
  	  	  3.3 Write 1 (one) to the bit of the data register ODR.
  	  	  3.4 Delay(500ms)
  
  	 Button.....
  	 	 1º When the button is pressed it prints a message to the SWV Trace Line
  	 	    of the debug port.
  
  	 */
  
  
  	//  Green LED pin PD12 OUTPUT
  
  	// Enables the clock of the peripheral GPIOD,
      // in the register of Enable of RCC peripheral Clock.
  	// Reset value: 0x0010 0000   [For this case it will not be necessary.]
  	uint32_t volatile * pRccAhb1Enr = (uint32_t *) RCC_AHB1_ENR_ADDR;
  	*pRccAhb1Enr |= (1 << 3);
  
  	// Enable of the clock of the peripheral GPIOA,
  	// in the register Enable of RCC peripheral Clock.
  	*pRccAhb1Enr |= (1 << 0);
  
  	// Green LED pin PD12 OUTPUT
      // Activate the MODE register of the port to config it as OUTPUT.
  	uint32_t volatile * pGpioDModer = (uint32_t *) GPIOD_MODER_ADDR;
  	*pGpioDModer &= ~(3 << 24);   // Reset value is 0x0.....0
  	*pGpioDModer |= (1 << 24);
  
  	// Button USER pin PA0 Input.
  	// Ativate the MODE of the port turning it into an INPUT.
  	uint32_t volatile * pGpioAModer = (uint32_t *) GPIOA_MODER_ADDR;
  	*pGpioAModer &= ~(3 << 0);    // Reset value is GPIOx_MODER_RESET_VALUE
  
  
  	/*
  	// OOTPUT of the LED.
  	GPIO port output data register (GPIOx_ODR) (x = A..I/J/K)
  	Address offset: 0x14
  	Reset value: 0x0000 0000
      */
  
  	uint32_t volatile * pGpioDOdr = (uint32_t *) GPIOD_ODR_ADDR;
  
  	int maxTime = (int)(ONE_SECOND * DELAY_SEC);
  	while(1){
  		delay(maxTime);
  	    // LED ON.
  		*pGpioDOdr |= (1 << 12);
  
  		delay(maxTime);
  		// LED OFF.
       	*pGpioDOdr &= ~(1 << 12);
  
       	if (getButtonState())
       		printf("User Button State: Pressed. \n");
       	else
       		printf("User Button State: Not pressed. \n");
  	}
  
  }
  
  