/*
 * Treugolnik.asm
 *
 *  Created: 15.09.20 10:53:55
 *   Author: Иванов И.Г.
 *
 *
 *
 *	ds1302  // 4(PD4)-CLK // 5(PD5)-DAT // 6(PD6)-RST(CE)
 *
 *
 *
 */ 


  .include "m328pdef.inc"

.equ fck	=	16000000		;частота в герцах
.equ BAUD	=	9600			;скорость
.equ UBRR_value	=	(fck/(BAUD*16))-1	;значение для регистра
.equ OneSecL = low(fck/64/10)	;мл.б. прерывание на 1/10 сек при предделителе 64
.equ OneSecH = high(fck/64/10)	;ст.б.	

.equ StepCount = 30				;количество шагов / на сколько интервалов разделена синусоида - 90
.equ StepWthMin = 20			;минимальное количество интервалов в одном 1/90 периода, максимальная скорость
.equ StepWthMax = 500          ;максимальное количество интервалов в одном 1/90 периода, минимальная скорость
.equ StepWthDelt = StepWthMax-StepWthMin         ;максимальное количество интервалов в одном 1/90 периода, минимальная скорость
.equ AcclrPin = PINC2			;потенциометр на скорость ADC2 - ножка А2


.equ PinFAtoV = PINB5			;13
.equ PinFBtoV = PINB3			;11 
.equ PinFCtoV = PINB1			;9

.equ PinFAtoG = PINB4           ;12 
.equ PinFBtoG = PINB2           ;10 
.equ PinFCtoG = PINB0           ;8



.DSEG				//0x0100


StepWth:			.BYTE 2			;ширина шага
StepStep:			.BYTE 2			;текущий подинтервал внутри шага
NumStep:			.BYTE 1			;номер шага из 90
TopWthFA:			.BYTE 2			;ширина верхнего уровня фазы А
TopWthFB:			.BYTE 2			;ширина верхнего уровня фазы B
TopWthFC:			.BYTE 2			;ширина верхнего уровня фазы C

.cseg				//0x0000

Label_01:           jmp Label_03	; Reset
					jmp Label_02	; External Interrupt Request 0
                    jmp Label_02	; External Interrupt Request 1
                    jmp Label_02	; Pin Change Interrupt Request 0
                    jmp Label_02	; Pin Change Interrupt Request 0
                    jmp Label_02	; Pin Change Interrupt Request 1
                    jmp Label_02	; Watchdog Time-out Interrupt
                    jmp Label_02	; Timer/Counter2 Compare Match A
                    jmp Label_02	; Timer/Counter2 Compare Match B
                    jmp Label_02	; Timer/Counter2 Overflow
                    jmp Label_02	; Timer/Counter1 Capture Event
                    jmp Int_T1MA_01	; Timer/Counter1 Compare Match A			// обработчик считывания ручки газа
                    jmp Label_02 	; Timer/Counter1 Compare Match B			
                    jmp Label_02	; Timer/Counter1 Overflow
                    jmp Int_T0MA_01	; TimerCounter0 Compare Match A
                    jmp Label_02	; TimerCounter0 Compare Match B
                    jmp Label_02	; Timer/Couner0 Overflow
                    jmp Label_02  	; SPI Serial Transfer Complete
                    jmp Label_02	; USART Rx Complete
                    jmp Label_02	; USART, Data Register Empty
                    jmp Label_02	; USART Tx Complete
                    jmp Label_02	; ADC Conversion Complete
                    jmp Label_02	; EEPROM Ready
                    jmp Label_02	; Analog Comparator
                    jmp Label_02	; Two-wire Serial Interface
                    jmp Label_02	; Store Program Memory Read
                    
Label_02:			reti
					cli
					jmp Label_01

					 ;поле констант


					 ;Фазы 
/*
FazeA:				.dw 22080, 30056, 32893, 30077, 32117, 32128, 26741, 16470, 3368, 0, 0, 0, 0, 0, 10253

FazeB:				.dw 32128, 26741, 16470, 3368, 0, 0, 0, 0, 0, 10253, 22080, 30056, 32893, 30077, 32117

FazeC:				.dw 0, 0, 0, 0, 10253, 22080, 30056, 32893, 30077, 32117, 32128, 26741, 16470, 3368, 0
*/

FazeA:				.dw 0,	22066,	30056,	32893,	32128,	26741,	12886,	0,	0,	0,	0,	0,	0,	0,	0

FazeB:				.dw 0,	0,	0,	0,	0,	0,	22066,	30056,	32893,	32128,	26741,	12886,	0,	0,	0

FazeC:				.dw 26741,	12886,	0,	0,	0,	0,	0,	0,	0,	0,	0,	22066,	30056,	32893,	32128


										
					 ;длина принимаемой команды в зависимости от параметра с учетом двух байт CRC
//LnRxCMD:			.db		0x04		;1 - команда запроса времени даты
					
					 ;таблица значений ацп для термопары с 10 до 70 град с шагом 1 град
//tmprgrid:			.dw      0x014A       ;   330		10
					

					 ;старт программы - инициализация
Label_03:           eor r1, r1			;r1 в ноль
					out SREG, r1		;в SREG ноль

                    ldi r28,low(RAMEND) 	;
                    ldi r29,high(RAMEND)	;конец рамы
                    out SPH, r29		; 
                    out SPL, r28		;загрузить стек 
										
					;настроить порты
					sbr r24,(1<<PinFAtoV)|(1<<PinFBtoV)|(1<<PinFCtoV)|(1<<PinFAtoG)|(1<<PinFBtoG)|(1<<PinFCtoG) ;как выход
					out DDRB,r24 
					
					in r24,PINB	
					cbr r24,(1<<PinFAtoV)|(1<<PinFBtoV)|(1<<PinFCtoV) ;отвязать от напряжения - мотор выключен
					sbr r24,(1<<PinFAtoG)|(1<<PinFBtoG)|(1<<PinFCtoG) ;привязать к нулю		 
					out PORTB,r24
					ldi r24,1
					//sts FazaAct,r24

					;Т0 настроить 
					ldi r24, 0b00000000	;
					sbr r24,(1<<WGM01)  ;мода 2 СТС 
					out TCCR0A,r24
					ldi r24, 0x00		;
					sbr r24,(1<<CS01)|(1<<CS00)  ;предделитель 64
					out TCCR0B, r24		;
                    
					ldi r24, 0x3		;
					out OCR0A, r24		;задать частоту 
					
					ldi r24, 0x00		;
					sbr r24,(1<<OCIE0A) 
					sts TIMSK0, r24		;прерывание по совпадению А

					;Т1 настроить на частоту обработки 1/4 сек
					ldi r24, 0b00000000	;
					sts TCCR1A, r24		; мода 4 CTC OCR1A Immediate MAX
                    ldi r24, 0b00001011	;clk/64, wgm12-1
					sts TCCR1B, r24		;предделитель
                    ldi r24, 0b00000000	;clk/64
					sts TCCR1C, r24		;предделитель
                    
					ldi r24,OneSecH     ;
					sts OCR1AH, r24		;задать частоту
					
					ldi r24,OneSecL     ;
					sts OCR1AL, r24		;задать частоту 

					
					ldi r24, 0x02		;
					sts TIMSK1, r24		;прерывание по совпадению А

					ldi r24,0		
					sts StepWth,r24
					sts StepWth+1,r24	;обнулить ширину шага
					sts StepStep,r24	;подинтервал внутри шага
					sts StepStep+1,r24	;
					sts NumStep,r24		;
					/*
					ldi r24,10		
					sts StepWth,r24
					
					ldi r24,9		
					sts StepStep,r24	;подинтервал внутри шага
					*/
					

					sei					;разрешить прерывание глобально
					;в режим ожидания
					ldi r24, 0x01
					out SMCR, r24		;режим ожидания Idle
Label_End:          sleep
					jmp Label_End


//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! обработчик прерывания T1 по A
Int_T1MA_01:		push r0 
                    push r1 
                    push r16
					in r16, SREG
					sbr r16,(1<<SREG_I)		;разрешить прерывания при восстановлении SREG, RETI не обязательно
					push r16
					push r17
					push r24				;X
                    push r25				;X
                    push r26				;X
                    push r27				;
					push r30				;Z
                    push r31				;
					sei						;разрешить прерывания глобально
					
					// потенциометр, регулятор оборотов
					;ldi r24,0b01000100		;по внешн питанию, мерить ADC4 - ножка А4
					ldi r24,AcclrPin		;ADC2 - ножка А2
					sbr r24,(1<<REFS0)		;AVCC with external capacitor at AREF pin
					cbr r24,(1<<REFS1)|(1<<ADLAR)
					sts ADMUX,R24 
					ldi r24,0b11000100		;включить, запустить, делитель на 16
					sts ADCSRA,R24
Int_T1MA_04:		lds r24,ADCSRA
					sbrc r24,ADSC
					jmp Int_T1MA_04			;ждем окончания расчета
					ldi r24,0b00000000		;ADC выключен
					sts ADCSRA,R24
					lds r16,ADCL			;считали значение ADC
					lds r17,ADCH
					cpi r17,0
					brne Int_T1MA_05		;продолжить если старший байт не ноль
					cpi r16,10
					brcs Int_T1MA_52		;если меньше 10 отключить
Int_T1MA_05:		ldi r24,0xFF
					ldi r25,0x03			;в r24;r25 3ff-значение потенциометра
					sub r24,r16
					sbc r25,r17				;в r24;r25 3ff-значение потенциометра
					/*
					ldi r16,StepWthDelt/1023;коэффициент соответствия 
					mul r24,r16
					mov r24,r0				;мл.байт
					push r1
					mul r25,r16
					mov r25,r0				;мл.байт
					pop r16
					add r25,r16
					*/
					adiw r24,StepWthMin
					
					cli
					sts StepWth,r24
					sts StepWth+1,r25
					sei
					jmp Int_T1MA_55
Int_T1MA_52:		;отключить
					clr r24
					cli	
					sts StepWth,r24
					sts StepWth+1,r24		;обнулить ширину шага
					sts StepStep,r24		;обнулить подинтервал внутри шага
					sts StepStep+1,r24		;
					sei
					
					sts NumStep,r24				;обнулить номер шага
Int_T1MA_55:		;вынуть стек
					pop r31
					pop r30
					pop r27
					pop r26
					pop r25
					pop r24
					pop r17
					pop r16
					out SREG,r16
					pop r16
					pop r1
					pop r0
					ret


					



//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//! обработчик прерывания T0 по A
Int_T0MA_01:		push r0 
                    push r16
					in r16, SREG
					sbr r16,(1<<SREG_I)		;разрешить прерывания при восстановлении SREG, RETI не обязательно
					push r16
					push r17
					push r24				;
                    push r25				;
                    push r26				;X
                    push r27				;
					push r30				;Z
                    push r31				;
					sei						;разрешить прерывания глобально

					lds r24,StepWth
					lds r25,StepWth+1		
					or r24,r25
					brne Int_T0MA_03		;если ширина шага не обнулена дальше
					;остановить двигатель
					in r16,PINB	
					cbr r16,(1<<PinFAtoV)|(1<<PinFBtoV)|(1<<PinFCtoV) ;отвязать от напряжения
					sbr r16,(1<<PinFAtoG)|(1<<PinFBtoG)|(1<<PinFCtoG) ;привязать к нулю		 
					out PORTB,r16			;мотор выключен
					jmp Int_T0MA_75
					;крутим
Int_T0MA_03:		lds r24,StepStep		;
					lds r25,StepStep+1		;
					;определить уровень_ до TopWthFX высокий, после низкий
					;по фазе А
					lds r16,TopWthFA
					cp r24,r16				;сравнить текущий подинтервал в шаге с поднинтервалом смены уровня
					lds r16,TopWthFA+1
					cpc r25,r16
					brcc Int_T0MA_31		;если смена уровня достигнута или пройдена перейти	
					in r16,PINB				;уровень в верх
					cbr r16,(1<<PinFAtoG)	;отвязать от нуля фазу А
					sbr r16,(1<<PinFAtoV)	;привязать к напряжению фазу А
					out PORTB,r16			;мотор выключен
					jmp Int_T0MA_33	
Int_T0MA_31:		in r16,PINB				;уровень в	низ
					cbr r16,(1<<PinFAtoV)	;отвязать от напряжения фазу А
					sbr r16,(1<<PinFAtoG)	;привязать к нулю фазу А
					out PORTB,r16			;мотор выключен
Int_T0MA_33:		;по фазе B
					lds r16,TopWthFB
					cp r24,r16				;сравнить текущий подинтервал в шаге с поднинтервалом смены уровня
					lds r16,TopWthFB+1
					cpc r25,r16
					brcc Int_T0MA_37		;если смена уровня достигнута или пройдена перейти	
					in r16,PINB				;уровень в верх
					cbr r16,(1<<PinFBtoG)	;отвязать от нуля фазу B
					sbr r16,(1<<PinFBtoV)	;привязать к напряжению фазу B
					out PORTB,r16			;мотор выключен
					jmp Int_T0MA_38	
Int_T0MA_37:		in r16,PINB				;уровень в	низ
					cbr r16,(1<<PinFBtoV)	;отвязать от напряжения фазу B
					sbr r16,(1<<PinFBtoG)	;привязать к нулю фазу B
					out PORTB,r16			;мотор выключен
Int_T0MA_38:		;по фазе C
					lds r16,TopWthFC
					cp r24,r16				;сравнить текущий подинтервал в шаге с поднинтервалом смены уровня
					lds r16,TopWthFC+1
					cpc r25,r16
					brcc Int_T0MA_41		;если смена уровня достигнута или пройдена перейти	
					in r16,PINB				;уровень в верх
					cbr r16,(1<<PinFCtoG)	;отвязать от нуля фазу C
					sbr r16,(1<<PinFCtoV)	;привязать к напряжению фазу C
					out PORTB,r16			;мотор выключен
					jmp Int_T0MA_42	
Int_T0MA_41:		in r16,PINB				;уровень в	низ
					cbr r16,(1<<PinFCtoV)	;отвязать от напряжения фазу C
					sbr r16,(1<<PinFCtoG)	;привязать к нулю фазу C
					out PORTB,r16			;мотор выключен
Int_T0MA_42:		;увеличить подинтервал		
					adiw r24,1				;увеличить r24,25 
					lds r16,StepWth
					cp r24,r16				;сравнить текущий подинтервал в шаге с шириной шага
					lds r16,StepWth+1
					cpc r25,r16
					brcc Int_T0MA_05		;если текущий подинтервал в шаге достиг конца шага
					jmp Int_T0MA_47			;не достиг
					;конец шага - следующий шаг
Int_T0MA_05:		lds r24,NumStep			;номер шага
					inc r24					;увеличить шаг
					cpi r24,StepCount
					brcs Int_T0MA_45		;не последний шаг
					clr r24					;обнулить номер шага
Int_T0MA_45:		sts NumStep,r24
					;определить номер подинтервала шага перехода уровня 1 в 0 в новом шаге 
					;фаза А
					ldi r30,low(FazeA*2)	;в Z адрес массива фазы A
					ldi r31,high(FazeA*2)		
					lds r24,NumStep			;номер шага
					add r30,r24	
					clr r24	
					adc r31,r24				;Z адрес шага
					lpm r16,Z				;процент верхнего уровня в шаге, процент от 0 до 128
					lds r24,StepWth
					lds r25,StepWth+1		;
					mul r24,r16				;делаем умножение шага на процент и делим на 128	
					mov r17,r0				;мл.байт
					push r1
					mul r25,r16
					pop r16
					add r0,r16
					mov r24,r0				;ср.байт
					clr r25
					adc r25,r1
					lsl R17
					rol r24
					rol r25
					sts TopWthFA,r24
					sts TopWthFA+1,r25
					;фаза B
					ldi r30,low(FazeB*2)	;в Z адрес массива фазы B
					ldi r31,high(FazeB*2)		
					lds r24,NumStep			;номер шага
					add r30,r24	
					clr r24	
					adc r31,r24				;Z адрес шага
					lpm r16,Z				;процент верхнего уровня в шаге, процент от 0 до 128
					lds r24,StepWth
					lds r25,StepWth+1		;
					mul r24,r16				;делаем умножение шага на процент и делим на 128	
					mov r17,r0				;мл.байт
					push r1
					mul r25,r16
					pop r16
					add r0,r16
					mov r24,r0				;ср.байт
					clr r25
					adc r25,r1
					lsl R17
					rol r24
					rol r25
					sts TopWthFB,r24
					sts TopWthFB+1,r25
					;фаза C
					ldi r30,low(FazeC*2)	;в Z адрес массива фазы C
					ldi r31,high(FazeC*2)		
					lds r24,NumStep			;номер шага
					add r30,r24	
					clr r24	
					adc r31,r24				;Z адрес шага
					lpm r16,Z				;процент верхнего уровня в шаге, процент от 0 до 128
					lds r24,StepWth
					lds r25,StepWth+1		;обнулить ширину шага
					mul r24,r16				;делаем умножение шага на процент и делим на 128	
					mov r17,r0				;мл.байт
					push r1
					mul r25,r16
					pop r16
					add r0,r16
					mov r24,r0				;ср.байт
					clr r25
					adc r25,r1
					lsl R17
					rol r24
					rol r25
					sts TopWthFC,r24
					sts TopWthFC+1,r25
					;нулевой подинтервал
					clr r24					;обнулить номер подинтервала
					clr r25
Int_T0MA_47:		sts StepStep,r24		;записать номер подинтервала
					sts StepStep+1,r25		;
					
Int_T0MA_75:		;вынуть стек
					pop r31
					pop r30
					pop r27
					pop r26
					pop r25
					pop r24
					pop r17
					pop r16
					out SREG,r16
					pop r16
					pop r0
					ret