feat: initial
This commit is contained in:
		
							
								
								
									
										263
									
								
								zh_avr_ac_dimmer.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								zh_avr_ac_dimmer.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,263 @@ | ||||
| #include "zh_avr_ac_dimmer.h" | ||||
|  | ||||
| static zh_avr_ac_dimmer_init_config_t _init_config = {0}; | ||||
| volatile static bool _is_dimmer_work = false; | ||||
| volatile static uint8_t _dimmer_value = 0; | ||||
| volatile static uint8_t _dimmer_count = 0; | ||||
| static bool _is_initialized = false; | ||||
|  | ||||
| static avr_err_t _zh_avr_ac_dimmer_validate_config(const zh_avr_ac_dimmer_init_config_t *config); | ||||
| static void _zh_avr_ac_dimmer_gpio_init(void); | ||||
| static avr_err_t _zh_avr_ac_dimmer_timer_init(void); | ||||
|  | ||||
| avr_err_t zh_avr_ac_dimmer_init(const zh_avr_ac_dimmer_init_config_t *config) | ||||
| { | ||||
|     ZH_ERROR_CHECK(_is_initialized == false, AVR_ERR_INVALID_STATE); | ||||
|     avr_err_t err = _zh_avr_ac_dimmer_validate_config(config); | ||||
|     ZH_ERROR_CHECK(err == AVR_OK, err); | ||||
|     _init_config = *config; | ||||
|     cli(); | ||||
|     _zh_avr_ac_dimmer_gpio_init(); | ||||
|     err = _zh_avr_ac_dimmer_timer_init(); | ||||
|     ZH_ERROR_CHECK(err == AVR_OK, err); | ||||
|     sei(); | ||||
|     _is_initialized = true; | ||||
|     return AVR_OK; | ||||
| } | ||||
|  | ||||
| avr_err_t zh_avr_ac_dimmer_start(void) | ||||
| { | ||||
|     ZH_ERROR_CHECK(_is_initialized == true, AVR_ERR_NOT_FOUND); | ||||
|     _is_dimmer_work = true; | ||||
|     return AVR_OK; | ||||
| } | ||||
|  | ||||
| avr_err_t zh_avr_ac_dimmer_stop(void) | ||||
| { | ||||
|     ZH_ERROR_CHECK(_is_initialized == true, AVR_ERR_NOT_FOUND); | ||||
|     _is_dimmer_work = false; | ||||
|     return AVR_OK; | ||||
| } | ||||
|  | ||||
| avr_err_t zh_avr_ac_dimmer_set(uint8_t value) | ||||
| { | ||||
|     ZH_ERROR_CHECK(_dimmer_value <= 100, AVR_ERR_INVALID_ARG); | ||||
|     _dimmer_value = value; | ||||
|     return AVR_OK; | ||||
| } | ||||
|  | ||||
| void zh_avr_ac_dimmer_isr_handler(void) | ||||
| { | ||||
|     uint8_t flag = false; | ||||
|     switch (_init_config.zero_cross_port) | ||||
|     { | ||||
|     case AVR_PORTB: | ||||
|         if ((PINB & (1 << _init_config.zero_cross_gpio)) == 0) | ||||
|         { | ||||
|             flag = true; | ||||
|         } | ||||
|         break; | ||||
|     case AVR_PORTC: | ||||
|         if ((PINC & (1 << _init_config.zero_cross_gpio)) == 0) | ||||
|         { | ||||
|             flag = true; | ||||
|         } | ||||
|         break; | ||||
|     case AVR_PORTD: | ||||
|         if ((PIND & (1 << _init_config.zero_cross_gpio)) == 0) | ||||
|         { | ||||
|             flag = true; | ||||
|         } | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|     if (_is_dimmer_work == true && flag == true) | ||||
|     { | ||||
|         if (_dimmer_value != 0) | ||||
|         { | ||||
|             if (_dimmer_value >= 100) | ||||
|             { | ||||
|                 TIMSK0 &= ~(1 << OCIE0A); | ||||
|                 switch (_init_config.triac_port) | ||||
|                 { | ||||
|                 case AVR_PORTB: | ||||
|                     PORTB |= (1 << _init_config.triac_gpio); | ||||
|                     _delay_us(ZH_TRIAC_TIME); | ||||
|                     PORTB &= ~(1 << _init_config.triac_gpio); | ||||
|                     break; | ||||
|                 case AVR_PORTC: | ||||
|                     PORTC |= (1 << _init_config.triac_gpio); | ||||
|                     _delay_us(ZH_TRIAC_TIME); | ||||
|                     PORTC &= ~(1 << _init_config.triac_gpio); | ||||
|                 case AVR_PORTD: | ||||
|                     PORTD |= (1 << _init_config.triac_gpio); | ||||
|                     _delay_us(ZH_TRIAC_TIME); | ||||
|                     PORTD &= ~(1 << _init_config.triac_gpio); | ||||
|                     break; | ||||
|                 default: | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 TCNT0 = 0; | ||||
|                 TIFR0 = (1 << OCF0A); | ||||
|                 TIMSK0 |= (1 << OCIE0A); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static avr_err_t _zh_avr_ac_dimmer_validate_config(const zh_avr_ac_dimmer_init_config_t *config) | ||||
| { | ||||
|     ZH_ERROR_CHECK(config != NULL, AVR_ERR_INVALID_ARG); | ||||
|     ZH_ERROR_CHECK((config->zero_cross_gpio >= 0 && config->zero_cross_gpio <= 7), AVR_ERR_INVALID_ARG); | ||||
|     ZH_ERROR_CHECK((config->triac_gpio >= 0 && config->triac_gpio <= 7), AVR_ERR_INVALID_ARG); | ||||
|     ZH_ERROR_CHECK(config->zero_cross_port >= AVR_PORTB && config->zero_cross_port <= AVR_PORTD, AVR_ERR_INVALID_ARG); | ||||
|     ZH_ERROR_CHECK(config->triac_port >= AVR_PORTB && config->triac_port <= AVR_PORTD, AVR_ERR_INVALID_ARG); | ||||
|     ZH_ERROR_CHECK(config->ac_dimmer_frequency >= ZH_50HZ && config->ac_dimmer_frequency <= ZH_400HZ, AVR_ERR_INVALID_ARG); | ||||
|     return AVR_OK; | ||||
| } | ||||
|  | ||||
| static void _zh_avr_ac_dimmer_gpio_init(void) | ||||
| { | ||||
|     switch (_init_config.zero_cross_port) | ||||
|     { | ||||
|     case AVR_PORTB: | ||||
|         DDRB &= ~(1 << _init_config.zero_cross_gpio); | ||||
|         PORTB |= (1 << _init_config.zero_cross_gpio); | ||||
|         PCICR |= (1 << PCIE0); | ||||
|         PCMSK0 |= (1 << _init_config.zero_cross_gpio); | ||||
|         break; | ||||
|     case AVR_PORTC: | ||||
|         DDRC &= ~(1 << _init_config.zero_cross_gpio); | ||||
|         PORTC |= (1 << _init_config.zero_cross_gpio); | ||||
|         PCICR |= (1 << PCIE1); | ||||
|         PCMSK1 |= (1 << _init_config.zero_cross_gpio); | ||||
|         break; | ||||
|     case AVR_PORTD: | ||||
|         DDRD &= ~(1 << _init_config.zero_cross_gpio); | ||||
|         PORTD |= (1 << _init_config.zero_cross_gpio); | ||||
|         PCICR |= (1 << PCIE2); | ||||
|         PCMSK2 |= (1 << _init_config.zero_cross_gpio); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
|     switch (_init_config.triac_port) | ||||
|     { | ||||
|     case AVR_PORTB: | ||||
|         DDRB |= (1 << _init_config.triac_gpio); | ||||
|         PORTB &= ~(1 << _init_config.triac_gpio); | ||||
|         break; | ||||
|     case AVR_PORTC: | ||||
|         DDRC |= (1 << _init_config.triac_gpio); | ||||
|         PORTC &= ~(1 << _init_config.triac_gpio); | ||||
|         break; | ||||
|     case AVR_PORTD: | ||||
|         DDRD |= (1 << _init_config.triac_gpio); | ||||
|         PORTD &= ~(1 << _init_config.triac_gpio); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static avr_err_t _zh_avr_ac_dimmer_timer_init(void) | ||||
| { | ||||
|     TCCR0A |= (1 << WGM01); | ||||
|     switch (F_CPU) | ||||
|     { | ||||
|     case 8000000: | ||||
|         switch (_init_config.ac_dimmer_frequency) | ||||
|         { | ||||
|         case ZH_50HZ: | ||||
|             OCR0A = 99; | ||||
|             TCCR0B |= (1 << CS01); | ||||
|             break; | ||||
|         case ZH_60HZ: | ||||
|             OCR0A = 82; | ||||
|             TCCR0B |= (1 << CS01); | ||||
|             break; | ||||
|         case ZH_400HZ: | ||||
|             OCR0A = 99; | ||||
|             TCCR0B |= (1 << CS00); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     case 16000000: | ||||
|         switch (_init_config.ac_dimmer_frequency) | ||||
|         { | ||||
|         case ZH_50HZ: | ||||
|             OCR0A = 24; | ||||
|             TCCR0B |= (1 << CS01) | (1 << CS00); | ||||
|             break; | ||||
|         case ZH_60HZ: | ||||
|             OCR0A = 165; | ||||
|             TCCR0B |= (1 << CS01); | ||||
|             break; | ||||
|         case ZH_400HZ: | ||||
|             OCR0A = 24; | ||||
|             TCCR0B |= (1 << CS01); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     case 20000000: | ||||
|         switch (_init_config.ac_dimmer_frequency) | ||||
|         { | ||||
|         case ZH_50HZ: | ||||
|             OCR0A = 249; | ||||
|             TCCR0B |= (1 << CS01); | ||||
|             break; | ||||
|         case ZH_60HZ: | ||||
|             OCR0A = 207; | ||||
|             TCCR0B |= (1 << CS01); | ||||
|             break; | ||||
|         case ZH_400HZ: | ||||
|             OCR0A = 249; | ||||
|             TCCR0B |= (1 << CS00); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     default: | ||||
|         return AVR_ERR_INVALID_ARG; | ||||
|         break; | ||||
|     } | ||||
|     return AVR_OK; | ||||
| } | ||||
|  | ||||
| ISR(TIMER0_COMPA_vect) | ||||
| { | ||||
|     if (_dimmer_count >= (100 - _dimmer_value)) | ||||
|     { | ||||
|         _dimmer_count = 0; | ||||
|         TIMSK0 &= ~(1 << OCIE0A); | ||||
|         switch (_init_config.triac_port) | ||||
|         { | ||||
|         case AVR_PORTB: | ||||
|             PORTB |= (1 << _init_config.triac_gpio); | ||||
|             _delay_us(ZH_TRIAC_TIME); | ||||
|             PORTB &= ~(1 << _init_config.triac_gpio); | ||||
|             break; | ||||
|         case AVR_PORTC: | ||||
|             PORTC |= (1 << _init_config.triac_gpio); | ||||
|             _delay_us(ZH_TRIAC_TIME); | ||||
|             PORTC &= ~(1 << _init_config.triac_gpio); | ||||
|         case AVR_PORTD: | ||||
|             PORTD |= (1 << _init_config.triac_gpio); | ||||
|             _delay_us(ZH_TRIAC_TIME); | ||||
|             PORTD &= ~(1 << _init_config.triac_gpio); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     ++_dimmer_count; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user