From 8789dded04b4e1a0d7343101c93c8a0ef44e0a92 Mon Sep 17 00:00:00 2001 From: Ibrahim Date: Sat, 8 Oct 2022 19:54:21 +0200 Subject: [PATCH] added ADC driver --- ADC/.cproject | 115 ++++++ ADC/.project | 27 ++ ADC/.settings/de.innot.avreclipse.core.prefs | 7 + .../org.eclipse.core.resources.prefs | 2 + ADC/src/adc.c | 78 +++++ ADC/src/adc.h | 64 ++++ ADC/src/common_macros.h | 34 ++ ADC/src/gpio.c | 328 ++++++++++++++++++ ADC/src/gpio.h | 99 ++++++ ADC/src/std_types.h | 40 +++ 10 files changed, 794 insertions(+) create mode 100644 ADC/.cproject create mode 100644 ADC/.project create mode 100644 ADC/.settings/de.innot.avreclipse.core.prefs create mode 100644 ADC/.settings/org.eclipse.core.resources.prefs create mode 100644 ADC/src/adc.c create mode 100644 ADC/src/adc.h create mode 100644 ADC/src/common_macros.h create mode 100644 ADC/src/gpio.c create mode 100644 ADC/src/gpio.h create mode 100644 ADC/src/std_types.h diff --git a/ADC/.cproject b/ADC/.cproject new file mode 100644 index 0000000..19f5d73 --- /dev/null +++ b/ADC/.cproject @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ADC/.project b/ADC/.project new file mode 100644 index 0000000..98245b7 --- /dev/null +++ b/ADC/.project @@ -0,0 +1,27 @@ + + + ADC + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + de.innot.avreclipse.core.avrnature + + diff --git a/ADC/.settings/de.innot.avreclipse.core.prefs b/ADC/.settings/de.innot.avreclipse.core.prefs new file mode 100644 index 0000000..2340aaf --- /dev/null +++ b/ADC/.settings/de.innot.avreclipse.core.prefs @@ -0,0 +1,7 @@ +avrtarget/ClockFrequency=16000000 +avrtarget/ExtRAMSize=0 +avrtarget/ExtendedRAM=false +avrtarget/MCUType=atmega32 +avrtarget/UseEEPROM=false +avrtarget/UseExtendedRAMforHeap=true +eclipse.preferences.version=1 diff --git a/ADC/.settings/org.eclipse.core.resources.prefs b/ADC/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..99f26c0 --- /dev/null +++ b/ADC/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/ADC/src/adc.c b/ADC/src/adc.c new file mode 100644 index 0000000..2fe13e3 --- /dev/null +++ b/ADC/src/adc.c @@ -0,0 +1,78 @@ + /****************************************************************************** + * + * Module: Analog to Digital Converter + * File Name: adc.h + * Description: source file for the ADC driver + * Author: Ibrahim Mohamed + * + *******************************************************************************/ + +#include +#include "adc.h" +#include "common_macros.h" +#include "gpio.h" + + +/******************************************************************************* + * Functions Definitions * + *******************************************************************************/ + + + +/* + * Description : + * Initialize the ADC: + */ +void ADC_init(const ADC_ConfigType * Config_Ptr){ + + /* ADMUX Register Bits Description: + * REFS1:0 = 00 to choose to connect external reference, internal reference or AVCC + * ADLAR = 0 right adjusted + * MUX4:0 = 00000 to choose channel 0 as initialization + */ + + ADMUX = 0; + + /* + * insert the required voltage value in the last 2 bits bits (REFS0 and REFS1) + * of ADMUX Register + */ + ADMUX = (ADMUX & 0x3F) | (Config_Ptr->ref_volt); + + + /* ADCSRA Register Bits Description: + * ADEN = 1 Enable ADC + * ADIE = 0 Disable ADC Interrupt + * ADATE = 0 Disable Auto Trigger + * ADPS2:0 = XXX to choose ADC_Clock (F_CPU/X where X is 2,4,8,16,32 or 64) --> ADC must operate in range 50-200Khz + */ + + ADCSRA = (1<prescaler); + +} + + + +/* + * Description : + * reads the channel from the ADC: + */ +uint16 ADC_readChannel(uint8 ch_num){ + + ch_num &= 0x07; /* Input channel number must be from 0 --> 7 */ + ADMUX &= 0X0E; /* Clear first 5 bits in the ADMUX (channel number MUX4:0 bits) before set the required channel */ + ADMUX = ADMUX | ch_num; /* Choose the correct channel by setting the channel number in MUX4:0 bits */ + + /* start conversion */ + SET_BIT(ADCSRA,ADSC); + + /* Polling */ + while(BIT_IS_CLEAR(ADCSRA,ADIF)); /* Wait for conversion to complete, ADIF becomes '1' */ + + /* clear the flag */ + SET_BIT(ADCSRA,ADIF); + + + return ADC; /* return the value of ADC register that holds the converted value */ +} diff --git a/ADC/src/adc.h b/ADC/src/adc.h new file mode 100644 index 0000000..a003239 --- /dev/null +++ b/ADC/src/adc.h @@ -0,0 +1,64 @@ + /****************************************************************************** + * + * Module: Analog to Digital Converter + * File Name: adc.h + * Description: header file for the ADC driver + * Author: Ibrahim Mohamed + * + *******************************************************************************/ + + +#ifndef SRC_ADC_H_ +#define SRC_ADC_H_ + +#include "std_types.h" + + + +/******************************************************************************* + * Types Declaration * + *******************************************************************************/ + +typedef enum{ + AREF_OFF = 0, + AVCC = 1, + INTERNAL_VOLTAGE = 4 +} ADC_ReferenceVolatge; + + +typedef enum{ + F_CPU_2 = 0, + F_CPU_2 = 1, + F_CPU_4, F_CPU_8, F_CPU_16, F_CPU_32, F_CPU_64, F_CPU_128 +} ADC_Prescaler; + + +typedef struct{ + ADC_ReferenceVolatge ref_volt; + ADC_Prescaler prescaler; +} ADC_ConfigType; + + +/******************************************************************************* + * Functions Prototypes * + *******************************************************************************/ + + + + +/* + * Description : + * Initialize the ADC: + */ +void ADC_init(const ADC_ConfigType * Config_Ptr); + + + +/* + * Description : + * reads the channel from the ADC: + */ +uint16 ADC_readChannel(uint8 ch_num); + + +#endif /* SRC_ADC_H_ */ diff --git a/ADC/src/common_macros.h b/ADC/src/common_macros.h new file mode 100644 index 0000000..68109b6 --- /dev/null +++ b/ADC/src/common_macros.h @@ -0,0 +1,34 @@ + /****************************************************************************** + * + * Module: Common - Macros + * File Name: Common_Macros.h + * Description: Commonly used Macros + * Author: Ibrahim Mohamed + * + *******************************************************************************/ + +#ifndef COMMON_MACROS +#define COMMON_MACROS + +/* Set a certain bit in any register */ +#define SET_BIT(REG,BIT) (REG|=(1<>num) | (REG<<(8-num)) ) + +/* Rotate left the register value with specific number of rotates */ +#define ROL(REG,num) ( REG= (REG<>(8-num)) ) + +/* Check if a specific bit is set in any register and return true if yes */ +#define BIT_IS_SET(REG,BIT) ( REG & (1<= NUM_OF_PINS_PER_PORT) || (port_num >= NUM_OF_PORTS)) + { + /* Do Nothing */ + } + else + { + /* Setup the pin direction as required */ + switch(port_num) + { + case PORTA_ID: + if(direction == PIN_OUTPUT) + { + SET_BIT(DDRA,pin_num); + } + else + { + CLEAR_BIT(DDRA,pin_num); + } + break; + case PORTB_ID: + if(direction == PIN_OUTPUT) + { + SET_BIT(DDRB,pin_num); + } + else + { + CLEAR_BIT(DDRB,pin_num); + } + break; + case PORTC_ID: + if(direction == PIN_OUTPUT) + { + SET_BIT(DDRC,pin_num); + } + else + { + CLEAR_BIT(DDRC,pin_num); + } + break; + case PORTD_ID: + if(direction == PIN_OUTPUT) + { + SET_BIT(DDRD,pin_num); + } + else + { + CLEAR_BIT(DDRD,pin_num); + } + break; + } + } +} + +/* + * Description : + * Write the value Logic High or Logic Low on the required pin. + * If the input port number or pin number are not correct, The function will not handle the request. + * If the pin is input, this function will enable/disable the internal pull-up resistor. + */ +void GPIO_writePin(uint8 port_num, uint8 pin_num, uint8 value) +{ + /* + * Check if the input port number is greater than NUM_OF_PINS_PER_PORT value. + * Or if the input pin number is greater than NUM_OF_PINS_PER_PORT value. + * In this case the input is not valid port/pin number + */ + if((pin_num >= NUM_OF_PINS_PER_PORT) || (port_num >= NUM_OF_PORTS)) + { + /* Do Nothing */ + } + else + { + /* Write the pin value as required */ + switch(port_num) + { + case PORTA_ID: + if(value == LOGIC_HIGH) + { + SET_BIT(PORTA,pin_num); + } + else + { + CLEAR_BIT(PORTA,pin_num); + } + break; + case PORTB_ID: + if(value == LOGIC_HIGH) + { + SET_BIT(PORTB,pin_num); + } + else + { + CLEAR_BIT(PORTB,pin_num); + } + break; + case PORTC_ID: + if(value == LOGIC_HIGH) + { + SET_BIT(PORTC,pin_num); + } + else + { + CLEAR_BIT(PORTC,pin_num); + } + break; + case PORTD_ID: + if(value == LOGIC_HIGH) + { + SET_BIT(PORTD,pin_num); + } + else + { + CLEAR_BIT(PORTD,pin_num); + } + break; + } + } +} + +/* + * Description : + * Read and return the value for the required pin, it should be Logic High or Logic Low. + * If the input port number or pin number are not correct, The function will return Logic Low. + */ +uint8 GPIO_readPin(uint8 port_num, uint8 pin_num) +{ + uint8 pin_value = LOGIC_LOW; + + /* + * Check if the input port number is greater than NUM_OF_PINS_PER_PORT value. + * Or if the input pin number is greater than NUM_OF_PINS_PER_PORT value. + * In this case the input is not valid port/pin number + */ + if((pin_num >= NUM_OF_PINS_PER_PORT) || (port_num >= NUM_OF_PORTS)) + { + /* Do Nothing */ + } + else + { + /* Read the pin value as required */ + switch(port_num) + { + case PORTA_ID: + if(BIT_IS_SET(PINA,pin_num)) + { + pin_value = LOGIC_HIGH; + } + else + { + pin_value = LOGIC_LOW; + } + break; + case PORTB_ID: + if(BIT_IS_SET(PINB,pin_num)) + { + pin_value = LOGIC_HIGH; + } + else + { + pin_value = LOGIC_LOW; + } + break; + case PORTC_ID: + if(BIT_IS_SET(PINC,pin_num)) + { + pin_value = LOGIC_HIGH; + } + else + { + pin_value = LOGIC_LOW; + } + break; + case PORTD_ID: + if(BIT_IS_SET(PIND,pin_num)) + { + pin_value = LOGIC_HIGH; + } + else + { + pin_value = LOGIC_LOW; + } + break; + } + } + + return pin_value; +} + +/* + * Description : + * Setup the direction of the required port all pins input/output. + * If the direction value is PORT_INPUT all pins in this port should be input pins. + * If the direction value is PORT_OUTPUT all pins in this port should be output pins. + * If the input port number is not correct, The function will not handle the request. + */ +void GPIO_setupPortDirection(uint8 port_num, GPIO_PortDirectionType direction) +{ + /* + * Check if the input number is greater than NUM_OF_PORTS value. + * In this case the input is not valid port number + */ + if(port_num >= NUM_OF_PORTS) + { + /* Do Nothing */ + } + else + { + /* Setup the port direction as required */ + switch(port_num) + { + case PORTA_ID: + DDRA = direction; + break; + case PORTB_ID: + DDRB = direction; + break; + case PORTC_ID: + DDRC = direction; + break; + case PORTD_ID: + DDRD = direction; + break; + } + } +} + +/* + * Description : + * Write the value on the required port. + * If any pin in the port is output pin the value will be written. + * If any pin in the port is input pin this will activate/deactivate the internal pull-up resistor. + * If the input port number is not correct, The function will not handle the request. + */ +void GPIO_writePort(uint8 port_num, uint8 value) +{ + /* + * Check if the input number is greater than NUM_OF_PORTS value. + * In this case the input is not valid port number + */ + if(port_num >= NUM_OF_PORTS) + { + /* Do Nothing */ + } + else + { + /* Write the port value as required */ + switch(port_num) + { + case PORTA_ID: + PORTA = value; + break; + case PORTB_ID: + PORTB = value; + break; + case PORTC_ID: + PORTC = value; + break; + case PORTD_ID: + PORTD = value; + break; + } + } +} + +/* + * Description : + * Read and return the value of the required port. + * If the input port number is not correct, The function will return ZERO value. + */ +uint8 GPIO_readPort(uint8 port_num) +{ + uint8 value = LOGIC_LOW; + + /* + * Check if the input number is greater than NUM_OF_PORTS value. + * In this case the input is not valid port number + */ + if(port_num >= NUM_OF_PORTS) + { + /* Do Nothing */ + } + else + { + /* Read the port value as required */ + switch(port_num) + { + case PORTA_ID: + value = PINA; + break; + case PORTB_ID: + value = PINB; + break; + case PORTC_ID: + value = PINC; + break; + case PORTD_ID: + value = PIND; + break; + } + } + + return value; +} diff --git a/ADC/src/gpio.h b/ADC/src/gpio.h new file mode 100644 index 0000000..bd4ff74 --- /dev/null +++ b/ADC/src/gpio.h @@ -0,0 +1,99 @@ + /****************************************************************************** + * + * Module: GPIO + * File Name: gpio.h + * Description: Header file for the AVR GPIO driver + * Author: Ibrahim Mohamed + * + *******************************************************************************/ + +#ifndef GPIO_H_ +#define GPIO_H_ + +#include "std_types.h" + +/******************************************************************************* + * Configurations * + *******************************************************************************/ +#define NUM_OF_PORTS 4 +#define NUM_OF_PINS_PER_PORT 8 + +#define PORTA_ID 0 +#define PORTB_ID 1 +#define PORTC_ID 2 +#define PORTD_ID 3 + +#define PIN0_ID 0 +#define PIN1_ID 1 +#define PIN2_ID 2 +#define PIN3_ID 3 +#define PIN4_ID 4 +#define PIN5_ID 5 +#define PIN6_ID 6 +#define PIN7_ID 7 + +/******************************************************************************* + * Types Declaration * + *******************************************************************************/ +typedef enum +{ + PIN_INPUT,PIN_OUTPUT +}GPIO_PinDirectionType; + +typedef enum +{ + PORT_INPUT,PORT_OUTPUT=0xFF +}GPIO_PortDirectionType; + +/******************************************************************************* + * Functions Prototypes * + *******************************************************************************/ + +/* + * Description : + * Setup the direction of the required pin input/output. + * If the input port number or pin number are not correct, The function will not handle the request. + */ +void GPIO_setupPinDirection(uint8 port_num, uint8 pin_num, GPIO_PinDirectionType direction); + +/* + * Description : + * Write the value Logic High or Logic Low on the required pin. + * If the input port number or pin number are not correct, The function will not handle the request. + * If the pin is input, this function will enable/disable the internal pull-up resistor. + */ +void GPIO_writePin(uint8 port_num, uint8 pin_num, uint8 value); + +/* + * Description : + * Read and return the value for the required pin, it should be Logic High or Logic Low. + * If the input port number or pin number are not correct, The function will return Logic Low. + */ +uint8 GPIO_readPin(uint8 port_num, uint8 pin_num); + +/* + * Description : + * Setup the direction of the required port all pins input/output. + * If the direction value is PORT_INPUT all pins in this port should be input pins. + * If the direction value is PORT_OUTPUT all pins in this port should be output pins. + * If the input port number is not correct, The function will not handle the request. + */ +void GPIO_setupPortDirection(uint8 port_num, uint8 direction); + +/* + * Description : + * Write the value on the required port. + * If any pin in the port is output pin the value will be written. + * If any pin in the port is input pin this will activate/deactivate the internal pull-up resistor. + * If the input port number is not correct, The function will not handle the request. + */ +void GPIO_writePort(uint8 port_num, uint8 value); + +/* + * Description : + * Read and return the value of the required port. + * If the input port number is not correct, The function will return ZERO value. + */ +uint8 GPIO_readPort(uint8 port_num); + +#endif /* GPIO_H_ */ diff --git a/ADC/src/std_types.h b/ADC/src/std_types.h new file mode 100644 index 0000000..883c571 --- /dev/null +++ b/ADC/src/std_types.h @@ -0,0 +1,40 @@ + /****************************************************************************** + * + * Module: Common - Platform Types Abstraction + * File Name: std_types.h + * Description: types for AVR + * Author: Ibrahim Mohamed + * + *******************************************************************************/ + +#ifndef STD_TYPES_H_ +#define STD_TYPES_H_ + +/* Boolean Data Type */ +typedef unsigned char boolean; + +/* Boolean Values */ +#ifndef FALSE +#define FALSE (0u) +#endif +#ifndef TRUE +#define TRUE (1u) +#endif + +#define LOGIC_HIGH (1u) +#define LOGIC_LOW (0u) + +#define NULL_PTR ((void*)0) + +typedef unsigned char uint8; /* 0 .. 255 */ +typedef signed char sint8; /* -128 .. +127 */ +typedef unsigned short uint16; /* 0 .. 65535 */ +typedef signed short sint16; /* -32768 .. +32767 */ +typedef unsigned long uint32; /* 0 .. 4294967295 */ +typedef signed long sint32; /* -2147483648 .. +2147483647 */ +typedef unsigned long long uint64; /* 0 .. 18446744073709551615 */ +typedef signed long long sint64; /* -9223372036854775808 .. 9223372036854775807 */ +typedef float float32; +typedef double float64; + +#endif /* STD_TYPE_H_ */