Commit a3cf0496 authored by Florian Zapf's avatar Florian Zapf
Browse files

Merge branch 'master' of gitlab.cs.fau.de:diygrp2/diy-project

parents a912dbbd 4a820cae
build/
libEZS/
libDIY/
ecosenv.sh/
ecos/
This diff is collapsed.
#ifndef DIY_ADC_H_INCLUDED
#define DIY_ADC_H_INCLUDED
/*!
* \defgroup adc DIY ADC Library
*/
/*!
* \file diy_adc.h DIY ADC Library
* \ingroup adc
* \brief Used to configure and sample the ADC for regular channel samples
*/
/* When using with the STM32F411E-DISCO the pins/channels:
* PA0/0
* PA4/4
* PA5/5
* PA6/6
* PA7/7
* PC0/11
* PC3/13
* PC4/14
* may already be used or are not available due to other peripherals.
* Pins/channels:
* PA1/1
* PA2/2
* PA3/3
* PB0/8
* PB1/9
* PC1/11
* PC2/12
* PC5/15
* should be available.
* Channel 16 and 17 are internal channels. Channel 18 is only for V_Bat.
*/
/*! \brief Structure to configure the ADC. Use the ADC define from libDIY/drivers/
* include/diy_adc.h for the adc value and sample_time. Use an Integer for the
* prescaler
*/
typedef struct {
uint32_t adc;
uint8_t sample_time;
uint32_t prescaler;
} diy_adc_config_t;
/*! \brief Initialize the on-board ADC.
* \param adc_config Struct containing the configuration of the ADC register
* \param channels Channel to be configured
* \param len_channels Number of channels in channels
*/
void diy_adc_init(diy_adc_config_t* adc_config, uint8_t channels[], uint8_t len_channels);
/*! \brief Reads the current ADC value from the channels.
* \param adc ADC peripheral
* \param channels Channels that should be read
* \param sample_val Array where the adc values are stored
* \param len_channels Number of channels to be read, sample_val and channels should be of same size
*/
void diy_adc_read(uint32_t adc, uint8_t channels[], uint16_t sample_val[], uint8_t len_channels);
#endif // DIY_ADC_H_INCLUDED
#ifndef DIY_GPIO_H_INCLUDED
#define DIY_GPIO_H_INCLUDED
#include <stdint.h>
/*!
* \defgroup gpio DIY GPIO Library
*/
/**
* \file diy_gpio.h DIY GPIO Library
* \ingroup gpio
* \brief Configure and use gpio pins
*/
/*!\brief Structure for initializing the GPIO Pins. For port, mode, type, speed
* and pull_up_down use the definitons from libDIY/drivers/include/diy_gpio.h.
* For alt_func see the STM32F411 data sheet and use an Interger from 0 to 15.
* \param port: GPIOA ... GPIOH
* \param mode: GPIO_MODE_OUTPUT (Pin as Output)
* GPIO_MODE_INPUT (Pin as Input)
GPIO_MODE_AF (Use Alternate function as described by alt_func, see data sheet)
GPIO_MODE_ANALOG (Use for ADC)
* \param type: GPIO_OTYPE_PP (Use PushPull configuration)
GPIO_OTYPE_OD (Use open drain configuration) https://electronics.stackexchange.com/questions/28091/push-pull-open-drain-pull-up-pull-down
* \param speed: GPIO_OSPEED_2MHZ, ..., GPIO_OSPEED_50MHZ
* \param pull_up_down: GPIO_PUPD_NONE, GPIO_PUPD_PULLUP, GPIO_PUPD_PULLDOWN
* \param alt_func: GPIO_AF0 ... GPIO_AF15
*/
typedef struct {
uint32_t port;
uint8_t mode;
uint8_t type;
uint8_t speed;
uint8_t pull_up_down;
uint8_t alt_func;
} diy_gpio_config_t;
/*!\brief Initialize the pins on one port with the same configuration
* \param gpio_config Struct containing the port register configuration
* \param pins Bitmask of the pins, if you want to use more than one pin OR-link
* them (GPIO1 | GPIO2 ...).
*/
void diy_gpio_init(diy_gpio_config_t* gpio_config, uint16_t pins);
/*!\brief Sets pins to high logic level
* \param port Port with the pins
* \param pin Bitmask of the pins
*/
void diy_gpio_set_pins(uint32_t port, uint16_t pin);
/*!\brief Sets pins to low logic level
* \param port Port with the pins
* \param pin Bitmask of the pins
*/
void diy_gpio_clear_pins(uint32_t port, uint16_t pin);
/*!\brief Inverts the pins logic level
* \param port Port with the pins
* \param pin Bitmask of the pins
*/
void diy_gpio_toggle_pins(uint32_t port, uint16_t pin);
/*!\brief Reads the current output status of one pin
* \param port Port with the pins
* \param pin Bitmask of the pins
* \returns 1 if pin is set to high, 0 otherwise
*/
uint8_t diy_gpio_read_pin_out(uint32_t port, uint16_t pin);
/*!\brief Reads the current logic levef of one pin
* \param port Port with the pin
* \param pin Bitmask of the pin
* \returns 1 if pin is pulled high, 0 otherweise
*/
uint8_t diy_gpio_read_pin(uint32_t port, uint16_t pin);
#endif //DIY_GPIO_H_INCLUDED
#ifndef DIY_INT_H_INCLUDED
#define DIY_INT_H_INCLUDED
/*!
* \defgroup interrupt DIY GPIO Interrupt Library
*/
/*!
* \file diy_int.h DIY GPIO Library
* \ingroup interrupt
* \brief Configure and use gpio pin's interrupts
*/
#include <stdint.h>
#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/exti.h>
/*
*
*/
void diy_init_button_int(uint32_t pin, enum exti_trigger_type trigger, uint8_t priority);
#endif // DIY_INT_H_INCLUDED
#ifndef DIY_TIM_H_INCLUDED
#define DIY_TIM_H_INCLUDED
/*!
* \defgroup timer DIY Timer Library
*/
/*!
* \file diy_tim.h DIY Timer Library
* \ingroup timer
* \brief Configure and use the onchip timers
*/
#include <stdint.h>
#include "libopencm3/stm32/timer.h"
// Channel Polarity Definitions
#define TIM_CCER_CCxNP_LOW 0
#define TIM_CCER_CCxNP_HIGH 1
/*! \brief Structure for configuring a timer. Use the definitions in libDIY/drivers
* include/diy_tim.h for timer, clock_div, alignment and count_direction. Use an
* integer for period
*/
typedef struct {
uint32_t timer;
uint32_t clock_div;
uint32_t alignment;
uint32_t count_direction;
uint32_t period;
} diy_tim_config_t;
/*! \brief Structure for configuring a channel. Use definitions in libDIY/drivers
* include/diy_tim.h for channel, mode and polarity. Use an integer for prescaler,
* repetition_counter and compare_value.
*/
typedef struct {
uint8_t channel;
uint8_t mode;
uint32_t prescaler;
uint32_t repetition_counter;
uint8_t polarity;
uint32_t compare_value;
} diy_tim_channel_config_t;
/* Timers available:
* TIM2
* TIM3
* TIM4
* TIM5 ! If you use the ezs_counter, do not use TIM5 !
* TIM9
* TIM10
* TIM11
* ! TIM 1 is an advanced timer and can not be used with this interface !
*/
/*! \brief Initialize a timer peripheral and starts the timer's counter
* \param tim_config Struct containing the configuration of the timer's register
*/
void diy_tim_init(diy_tim_config_t* tim_config);
/* Channels and pins for
* TIM2: (PA0, PA5, PA15)/CH1, (PA1, PB3)/CH2, (PA2, PB10)/CH3, PA3/CH4
* TIM3: (PA6, PB4, PC6)/CH1, (PA7, PB5, PC7)/CH2, (PB0, PC8)/CH3, (PB1, PC9)/CH4,
* TIM4: (PB6, PD12)/CH1, (PB7, PD13)/CH2, (PB8, PD14)/CH3, (PB9, PD15)/CH4
* TIM5: PA0/CH1, PA1/CH1, PA2/CH3, PA3/CH4
* TIM9: PA2/CH1, PA3/CH2
* TIM10: PB8/CH1
* TIM11: PB9/CH1
*/
/*! \brief Initialize a timer output channel and enables it's output
* \param channel_config Struct containing the configuration of the channel's register
* \param timer Timer peripheral of the channel
*/
void diy_tim_channel_init(diy_tim_channel_config_t* channel_config, uint32_t timer);
/*! \brief Starts the timer's counter
* \param timer Timer peripheral
*/
void diy_tim_start(uint32_t timer);
/*! \brief Stops the timer's counter
* \param timer Timer peripheral
*/
void diy_tim_stop(uint32_t timer);
/*! \brief Starts the channel's output
* \param timer Timer peripheral
* \param channel Channel ID
*/
void diy_tim_channel_start(uint32_t timer, enum tim_oc_id channel);
/*! \brief Stops the channel's output
* \param timer Timer peripheral
* \param channel Channel ID
*/
void diy_tim_channel_stop(uint32_t timer, enum tim_oc_id channel);
/*! \brief Sets the channel's capture compare value
* \param timer Timer peripheral
* \param channel Channel ID
* \param compare_value New capture compare value
*/
void diy_tim_channel_set_compare_value(uint32_t timer, enum tim_oc_id channel, uint32_t compare_value);
#endif // DIY_TIM_H_INCLUDED
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/adc.h>
#include "diy_adc.h"
#include "diy_gpio.h"
/*
* Function for initializing the onboard ADC and the channels with linked
* pins. The function assumes that the GPIO Pins have already been configured
* for ADC use.
*/
void diy_adc_init(diy_adc_config_t* adc_config, uint8_t channels[], uint8_t len_channels){
// Activate Clock for ADC, STM32F411E only has one ADC, so no selection is necessary
rcc_periph_clock_enable(RCC_ADC1);
// Power off ADC during setup (necessary?)
adc_power_off(adc_config->adc);
// Turn of scanning mode
adc_disable_scan_mode(adc_config->adc);
// Set sample time for channels
uint8_t i;
// Alternative: adc_set_sample_time_on_all_channels(adc, time)
for(i = 0; i < len_channels; i++){
adc_set_sample_time(adc_config->adc, channels[i], adc_config->sample_time);
}
// Power on ADC after setup
adc_power_on(adc_config->adc);
// ADC should be ready after 3 ms
}
/*
* Function to read out a set of up to 16 channels and return their
* values in array of the same order as the input array's channels
*/
void diy_adc_read(uint32_t adc, uint8_t channels[], uint16_t sample_val[], uint8_t len_channels){
/* adc_read_regular returns uin32_t, but only lower 16 bits are used when
* only one ADC is present or more ADC2 is available and dual mode is on.
*/
// Set channels to be sampled in the step
adc_set_regular_sequence(adc, len_channels, channels);
// Start sampling channels and wait for finish
uint8_t i;
for(i = 0;i < len_channels;i++){
adc_start_conversion_regular(adc);
while(!adc_eoc(adc)); // Flag set after each channels conversion
sample_val[i] = (uint16_t) adc_read_regular(adc);
}
}
#include "diy_gpio.h"
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
static enum rcc_periph_clken diy_gpio_get_rcc_periph(uint32_t port){
enum rcc_periph_clken rcc_periph;
switch(port){
case GPIOA: rcc_periph = RCC_GPIOA;
break;
case GPIOB: rcc_periph = RCC_GPIOB;
break;
case GPIOC: rcc_periph = RCC_GPIOC;
break;
case GPIOD: rcc_periph = RCC_GPIOD;
break;
case GPIOE: rcc_periph = RCC_GPIOE;
break;
case GPIOH: rcc_periph = RCC_GPIOH;
break;
default: rcc_periph = 0xFFFF;
break;
}
return rcc_periph;
}
void diy_gpio_init(diy_gpio_config_t* gpio_config, uint16_t pins){
// Get RCC define based on Port
enum rcc_periph_clken rcc_periph;
rcc_periph = diy_gpio_get_rcc_periph(gpio_config->port);
if(rcc_periph == 0xFFFF){
return;
}
else{
// Activate clock for Port
rcc_periph_clock_enable(rcc_periph);
}
// Set GPIO port registers MODER, PUPDR
gpio_mode_setup(gpio_config->port,
gpio_config->mode,
gpio_config->pull_up_down,
pins);
// Depending on pin mode set other registers
switch(gpio_config->mode){
// Set GPIO port registers OTYPER, OSPEEDR for output mode
case GPIO_MODE_OUTPUT: gpio_set_output_options(gpio_config->port,
gpio_config->type,
gpio_config->speed,
pins);
gpio_clear(gpio_config->port, pins);
break;
// Set GPIO port register AFRL for alternative function mode
case GPIO_MODE_AF: gpio_set_af(gpio_config->port,
gpio_config->alt_func,
pins);
break;
default: break;
}
}
/* Wrapper function for libopencm3 set pin function to have a unified
* interface. For multiple pins OR-link them (GPIO1 | GPIO2 ...).
*/
void diy_gpio_set_pins(uint32_t port, uint16_t pin){
gpio_set(port, pin);
}
/* Wrapper function for libopencm3 clear pin function to have a unified
* interface. For multiple pins OR-link them (GPIO1 | GPIO2 ...).
*/
void diy_gpio_clear_pins(uint32_t port, uint16_t pin){
gpio_clear(port, pin);
}
/* Wrapper function for libopencm3 toggle pin function to have a unified
* interface. For multiple pins OR-link them (GPIO1 | GPIO2 ...).
*/
void diy_gpio_toggle_pins(uint32_t port, uint16_t pin){
gpio_toggle(port, pin);
}
/* Function to query the state of one output pin
* 1 if pin is set, 0 otherwise
*/
uint8_t diy_gpio_read_pin_out(uint32_t port, uint16_t pin){
uint16_t odr_reg = 0;
odr_reg = (uint16_t) GPIO_ODR(port);
if(odr_reg & pin){
return (uint8_t) 1;
}
return (uint8_t) 0;
}
uint8_t diy_gpio_read_pin(uint32_t port, uint16_t pin){
uint16_t idr_reg = 0;
idr_reg = gpio_port_read(port);
if(idr_reg & pin){
return (uint8_t) 1;
}
return (uint8_t) 0;
}
#include "diy_int.h"
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
static uint8_t get_pin_interrupt(uint32_t pin){
switch(pin){
case GPIO0: return NVIC_EXTI0_IRQ;
default: return UINT8_MAX;
}
}
void diy_init_button_int(uint32_t pin, enum exti_trigger_type trigger, uint8_t priority){
uint8_t interrupt = get_pin_interrupt(pin);
if(interrupt == UINT32_MAX){
return;
}
nvic_enable_irq(NVIC_EXTI0_IRQ);
// Activate interrupt for pin
exti_select_source(EXTI0, GPIOA);
// Change trigger mode
exti_set_trigger(EXTI0, EXTI_TRIGGER_BOTH);
exti_enable_request(EXTI0);
}
#include "diy_tim.h"
#include "libopencm3/stm32/rcc.h"
/* \brief Private function for determining the peripheral clock for the Timer.
*/
static enum rcc_periph_clken diy_tim_get_rcc_periph(uint32_t timer){
enum rcc_periph_clken rcc_periph;
switch(timer){
case TIM2: rcc_periph = RCC_TIM2;
break;
case TIM3: rcc_periph = RCC_TIM3;
break;
case TIM4: rcc_periph = RCC_TIM4;
break;
case TIM5: rcc_periph = RCC_TIM5;
break;
case TIM9: rcc_periph = RCC_TIM9;
break;
case TIM10: rcc_periph = RCC_TIM10;
break;
case TIM11: rcc_periph = RCC_TIM11;
break;
default: rcc_periph = 0xFFFF;
break;
}
return rcc_periph;
}
/* \brief Initialize one of the available timers. TIM1 is an advanced timer that
* can not be used with this interface. The timer will always run in upadte
* master mode. Preload is always enabled.
*/
void diy_tim_init(diy_tim_config_t* tim_config){
enum rcc_periph_clken rcc_periph;
rcc_periph = diy_tim_get_rcc_periph(tim_config->timer);
if(rcc_periph == 0xFFFF){
return;
}
else{ // Activate clock for timer
rcc_periph_clock_enable(rcc_periph);
}
timer_set_mode(tim_config->timer,
tim_config->clock_div,
tim_config->alignment,
tim_config->count_direction);
timer_set_period(tim_config->timer,
tim_config->period);
timer_set_master_mode(tim_config->timer, TIM_CR2_MMS_UPDATE);
timer_enable_preload(tim_config->timer);
// Start timer
timer_enable_counter(tim_config->timer);
}
void diy_tim_channel_init(diy_tim_channel_config_t* channel_config, uint32_t timer){
timer_set_oc_mode(timer,
(enum tim_oc_id) channel_config->channel,
(enum tim_oc_mode) channel_config->mode);
if(channel_config->polarity == TIM_CCER_CCxNP_HIGH){
timer_set_oc_polarity_high(timer, channel_config->channel);
}
if(channel_config->polarity == TIM_CCER_CCxNP_LOW){
timer_set_oc_polarity_low(timer, channel_config->channel);
}
timer_set_oc_value(timer,
channel_config->channel,
channel_config->compare_value);
timer_enable_oc_preload(timer, channel_config->channel);
// Enable channel output
timer_enable_oc_output(timer, channel_config->channel);
}
void diy_tim_start(uint32_t timer){
timer_enable_counter(timer);
}
void diy_tim_stop(uint32_t timer){
timer_disable_counter(timer);
}
void diy_tim_channel_start(uint32_t timer, enum tim_oc_id channel){
timer_enable_oc_output(timer, channel);
}
void diy_tim_channel_stop(uint32_t timer, enum tim_oc_id channel){
timer_disable_oc_output(timer, channel);
}
void diy_tim_channel_set_compare_value(uint32_t timer, enum tim_oc_id channel, uint32_t compare_value){
timer_set_oc_value(timer, channel, compare_value);
}
#ifndef DIY_DS18B20_H_INCLUDED
#define DIY_DS18B20_H_INCLUDED
#include <stdint.h>
/* Defines */
/* \brief Initialize the pins for Rx and Tx, also sends a test master reset to
* check if the sensor is connected.
*/
void diy_ds18b20_init(diy_ds18b20_t* ds18b20_sensor);
void diy_ds18b20_read_temp(diy_ds18b20_t* ds18b20_sensor);
float diy_ds18b20_dig_to_cel(uint16_t dig_sensor_val);
#endif // DIY_DS18B20_H_INCLUDED
#include "diy_ds18b20.h"
#include "diy_gpio.h"
#include "ezs_delay.h"
#include "libopencm3/stm32/gpio.h"
void diy_ds18b20_init(diy_ds18b20_t* sensor){
}
/* See data sheet page 18 for order of operation */
void diy_ds18b20_read_temp(diy_ds18b20_t* sensor){
}
float diy_ds18b20_dig_to_cel(uint16_t sensor_val_dig){
}
/*!
* @file ezs_adc.c
* @brief A very simple AD converter, based on Fail*
* @author Martin Hoffmann
* \ingroup adc
*/
#include <stdint.h>
#include "ezs_dac.h"
static volatile uint8_t ezs_adc_in_register;
/*!
* \brief Get a value from the ADC
*/
uint8_t ezs_adc_read(void){
return ezs_adc_in_register;
}
#define EZS_HPET_ADDR 0xFED00000