From da34d97efb21719b2b332f8c60b2750d11bcde1f Mon Sep 17 00:00:00 2001 From: Otto Mattik Date: Thu, 8 Jul 2021 18:10:55 +0200 Subject: git: update to v1.0 --- avr/pwm.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 avr/pwm.c (limited to 'avr/pwm.c') diff --git a/avr/pwm.c b/avr/pwm.c new file mode 100644 index 0000000..6860053 --- /dev/null +++ b/avr/pwm.c @@ -0,0 +1,223 @@ +/************************************************************************/ +/* */ +/* File: avr/pwm.c */ +/* Description: pulse width modulation driver. */ +/* Version: 1.0 */ +/* Author: Otto Mattik */ +/* */ +/* (C)Copyright Otto Mattik 2014-2021. */ +/* */ +/* This file is a part of 'armen' (a tiny operating system). */ +/* 'armen' is distributed under the CeCILL-V2.1 licence. For more */ +/* details about this licence, please visit the website cecill.info */ +/* */ +/************************************************************************/ + +#ifndef AVR_GPIO_C + #error "do not use this code directly, it must be included via gpio.c" +#endif + +#if defined(__AVR_ATtiny84__)\ + || defined(__AVR_ATtiny85__) + #if defined(UART) && (UART != 0) + #error "pwm and uart, used together, are incompatible" + #endif +#endif + +#if defined(__AVR_ATtiny84__) + #define GPIO_MAX_PWM 1 +#elif defined(__AVR_ATtiny841__) + #define GPIO_MAX_PWM 2 +#elif defined(__AVR_ATtiny85__) + #define GPIO_MAX_PWM 1 +#elif defined(__AVR_ATtiny1634__) + #define GPIO_MAX_PWM 1 +#elif defined(__AVR_ATmega328P__) + #define GPIO_MAX_PWM 2 +#elif defined(__AVR_ATmega2560__) + #define GPIO_MAX_PWM 5 +#endif + +/* + __AVR_ATtiny84__ + t1, 16 bits, OC1A=PA6/6, OC1B=PA5/5 + __AVR_ATtiny85__ + t1, 8 bits, OC1A=PB1/1, OC1B=PB4/4 + __AVR_ATtiny841__ + t1, 16 bits, OC1A=TOCC1|TOCC3|TOCC5|TOCC7, OC1B=TOCC0|TOCC2|TOCC4|TOCC6 + t2, 16 bits, OC2A=TOCC1|TOCC3|TOCC5|TOCC7, OC2B=TOCC0|TOCC2|TOCC4|TOCC6 + __AVR_ATtiny1634__ + t1, 16 bits, OC1A=PC0/16, OC1B=PB3/11 + __AVR_ATmega328P__ + t1, 16 bits, OC1A=PB1/1, OC1B=PB2/2 + t2, 8 bits, OC2A=PB3/3, OC2B=PD3/19 + __AVR_ATmega2560__ + t1, 16 bits, OC1A=PB5/13, OC1B=PB6/14, 0C1C=PB7/15 + t2, 8 bits, OC2A=PB4/12, OC2B=PH6/62 + t3, 16 bits, OC3A=PE3/35, OC3B=PE4/36, OC3C=PE5/37 + t4, 16 bits, OC4A=PH3/59, OC4B=PH4/60, OC4C=PH5/61 + t5, 16 bits, OC5A=PL3/83, OC5B=PL4/84, OC5C=PL5/85 +*/ +static uint8_t pwm_freq = 0; + +static struct { + uint8_t* tccra; + uint8_t* tccrb; + uint8_t* ocra; + uint8_t* ocrb; + uint8_t* ocrc; + uint8_t modea; + uint8_t modeb; + uint8_t bytes; +} pwms[GPIO_MAX_PWM] = { +#if defined(__AVR_ATtiny84__) + { 0x004F, 0x004E, 0x004A, 0x0048, 0x0000, + (1<= 1 && scale <= 5 ) +#endif + { + uint8_t i; + + /* set fast pwm (8 bits) mode with OCnA and 0CnB cleared on compare match */ + for( i = 0; i < GPIO_MAX_PWM; i++ ) + { + *pwms[i].tccra = pwms[i].modea; +#if defined(__AVR_ATmega328P__)\ + || defined(__AVR_ATmega2560__) + if( i == 1 && scale > 2 ) + { + uint8_t value; + if( scale == 3 ) + value = 4; + else if( scale == 4 ) + value = 6; + else + value = 7; + *pwms[i].tccrb = pwms[i].modeb | value; + else +#endif + *pwms[i].tccrb = pwms[i].modeb | scale; + *pwms[i].ocra = 0; + *pwms[i].ocrb = 0; + if( pwms[i].ocrc != 0 ) + *pwms[i].ocrc = 0; + } + } +} + +void gpio_pwm_set( uint8_t gpio, uint8_t percent ) +{ +#ifdef CHECK_PARAM + if( gpio < (GPIO_MAX_PORT << 3) ) +#endif + { + uint8_t timer = 0; + +#if defined(__AVR_ATtiny84__) + if( gpio == 6 || gpio == 5 ) + { + gpio = 6 - gpio; +#elif defined(__AVR_ATtiny85__) + if( gpio == 1 || gpio == 4 ) + { + gpio = (gpio == 1 ? 0 : 1); +#elif defined(__AVR_ATtiny841__) + if( gpio <= 7 ) + { + /* OC1A=TOCC1|TOCC3|TOCC5|TOCC7 + OC1B=TOCC0|TOCC2|TOCC4|TOCC6 */ + if( gpio <= 3 ) + TOCPMSA0 |= (01 << (gpio << 2)); + else + TOCPMSA1 |= (01 << ((gpio - 4) << 2)); + TOCPMCOE |= (1 << gpio); + gpio = ((gpio & 1) == 1 ? 0 : 1); +#elif defined(__AVR_ATtiny1634__) + if( gpio == 16 || gpio == 11 ) + { + gpio = (gpio == 16 ? 0 : 1); +#elif defined(__AVR_ATmega328P__) + if( gpio == 1 || gpio == 2 ) + gpio -= 1; + else if( gpio == 3 || gpio == 19 ) + { + gpio = (gpio == 3 ? 0 : 1); + timer = 1; + } + else + return; + { +#elif defined(__AVR_ATmega2560__) + if( gpio >= 13 || gpio <= 15 ) + gpio -= 13; + else if( gpio == 12 || gpio == 62 ) + { + gpio = (gpio == 12 ? 0 : 1); + timer = 1; + } + else if( gpio >= 35 && gpio <= 37 ) + { + gpio -= 35; + timer = 2; + } + else if( gpio >= 59 && gpio <= 61 ) + { + gpio -= 59; + timer = 3; + } + else if( gpio >= 83 && gpio <= 85 ) + { + gpio -= 83; + timer = 4; + } + else + return; + { +#endif + percent = (255 * percent) / 100; + if( gpio == 0 ) + *pwms[timer].ocra = percent; +#if defined(__AVR_ATmega2560__) + else if( gpio == 2 ) + *pwms[timer].ocrc = percent; +#endif + else + *pwms[timer].ocrb = percent; + } + } +} -- cgit v1.2.1