;		Smps Pid  @ 9.6Mhz 
         
.include		"tn13def.inc"

.equ	SetPoint	= $d1			; Desired Voltage, 5.25V

.equ	PwmNon		= $83			; Fast Non Inverting PWM Режим быстрый шим не инвертированный значение

;-----	
.def	Null		= r4			; Zero Constant нуль	
.def	Volt		= r5			; A2D Voltage напряжение ацп

.def	PrerrL		= r6			; Present Error Registers регистры текущей ошибки
.def	PrerrH		= r7
			
.def	PaerrL		= r8			; Past Error Registers	регистры прошлой ошибки
.def	PaerrH		= r9				
		 
.def	IntegL		= r10			; Integral Component Registers регистры интегральной составялющей
.def	IntegH		= r11			

.def	AccumL		= r12			; Sum Accumulation Registers регистры накопления
.def	AccumH		= r13			

.def	DeltaL		= r14			; Difference/Delta Component Registers регистры дефиринциальной составляющей 
.def	DeltaH		= r15			
       
.def	Temp		= r16			; Scratch Registers временные регистры	
.def	TempA		= r17	

;------         
.Cseg
         
.Org	$0000
			
;-----         
Reset:			    						
      	ldi	Temp,	RamEnd		
     	out	Spl,	Temp		; Set Stack Pointer указываем начало стека
	
	ldi	Temp,	$5b		; Calibrate Internal Oscillator записываем калибровку тактового генератора
	out	OscCal,	Temp

	sbi	DdrB,	Ddb0		; Enable PBO as Output включаем  PBO как вывод

	sbi	AcsR,	Acd		; Disable Comparator  вырубаем компаратор
      			 
   	sbi	DidR0,	Adc2d		; Disable Adc2d Digital Input выключаем цифровой вход на выводе ацп

	ldi	Temp,	$42		; Adc2 + (AdLar=0) + 1.1V Analog Ref включаем внутреннию опору
	out	AdMux,	Temp	

	ldi	Temp,	$84		; Init + 222 Khz A2D Sample Rate настраиваем скорость ацп
	out	AdCsrA,	Temp 

	ldi	Temp,	$01		; No Prescaler ;Pwm Freq = 37500 Hz включаем тактование счётчика шим
	out	TccR0B,	Temp		

	ldi	Temp,	PwmNon		; Fast PWM; Non Invering Mode  включаем режим быстрый шим не инвертированный
	out	TccR0A,	Temp	

	clr	Null			; Set Null Constant to Zero сбрасываем константу нуль

;-----         
Main:									    
	sbi	AdCsrA,	Adsc		; En A/D Conv		запускаем преобразование
         
      	sbis	AdCsrA,	Adif		; Conv Comp ? 	 проверяем что преобразование завершилось
	rjmp	pc-1

	in	Volt,	AdcL		; Read Low byte читаем младший байт

      	in	Temp,	AdcH		; Read Hi order 2 Bits читаем старший бит

	sbi	AdCsrA,	Adif		; Clr Conversion Flag сбрасываем флаг завершения преобразования

	cpi	Temp,	$03		; If Hi Order 2 Bits = "11" then OK если 2 старших байта равны 11 то  ок
	breq	Error

	clr	Volt			; Else Low Byte = Zero Иначе сбрасываем младший байт в нуль
; накой это сделано не понятно

;-----
; обработка сигнала ошибки	
Error:

;* Finds Difference (Error) between the Reference Voltage in SetPoint and 
;* the Current Voltage in Volt
; находим разницу между опорным значением в SetPoint и текущем напряжении 

;* PrerrH:PrerrL = SetPoint - Volt

;* Input  Variable = SetPoint   desired Output Voltage желаемое выходное напряжение

;* Output Variable = PrerrH:PrerrL    Signed Error. Признак ошибки

	
	ldi	TempA,	SetPoint		; Get Reference Voltage получаем опорное напряжение

	clr	PrerrH				; Clear Error High сбрасываем страший регистр текущей ошибки 

	sub	TempA,	Volt			; Subtract Actual from Reference Voltage вычитаем текущее из опорного напряжения

	brcc	pc+2				; Was there a Borrow ?	было ли занятие 

	dec	PrerrH				; If Yes then PrerrH = $ff; Else EOH = $00 если да то PrerrH = $ff; Иначе PrerrH=$00

	mov	PrerrL,	TempA			; store in current Error сохраняем текущию ошибку

;----
обьщёт пропорциональной компоненты
Prop:

;* AccumH:AccumL = PrerrH:PrerrL * Kp

;* Kp = 8   produced by 3 Left Shifts делаем 3 сдвига в лево

;* Input  Variable = PrerrH:PrerrL = Error and  Kp is the Proportional Gain factor 
;входные данные  ошибка и коофициент усиления 

;* Output Variable = AccumH:AccumL =  Proportional Component.
;выходные данные пропорциональная компонента


	movw	AccumH:AccumL,PrerrH:PrerrL	; Mov Error into Sum ошибку перемещаем текушию ошибку в сумму

	lsl	AccumL				; Multiply Sum by 8 уиножаем сумму на 8
	rol	AccumH
	lsl	AccumL				
	rol	AccumH
	lsl	AccumL				; Proportional result in Sum  в сумме пропорциональная компонента
	rol	AccumH

;----
Diff:

;* Finds difference/Delta between Present Loop Error and Previous Loop Error
; находим рахность между текущей ошибкой и прошлой ошибкой
;* DeltaH:DeltaL =(PaerrH:PaerrL - PrerrH:PrerrL) * Kd: Kd = 8 (Three Left Shifts)

;* Input Variable входные данные
;* PaerrH:PaerrL Previous Loop Error приведушия ошибка: PrerrH:PrerrL Pesent Loop Error настоящия ошибка
;* Kd = Differential Gain factor коофициент диференциального усиления

;* Output Variable = DeltaH:DeltaL =  Differentional Component. диференциальная компанента


	Movw	DeltaH:DeltaL,PrerrH:PrerrL	; Move Error into Delta перемещаем текушию ошибку в диференциальную переменную
	
	sub	DeltaL,	PaerrL			; Subtract Previous from Current Error вычитаем из текущей ошибке прошлую
	sbc	DeltaH,	PaerrH			; and store in Delta и сохраняем в диференциальную переменную

	lsl	DeltaL				; Multiply Delta by 8 уножаем диференциальную переменную на 8
	rol	DeltaH
	lsl	DeltaL				
	rol	DeltaH
	lsl	DeltaL				
	rol	DeltaH

;-----
Integ:

;* Multiplies Present Error by Ki and adds result to IntegH:IntegL
; умножаем приведущию ошибку на коофициент инегрирования
;* IntegH:IntegL =IntegH:IntegL + PrerrH:PrerrL * Ki: Ki = 8

;* Input Variables:	
;* PrerrH:PrerrL				: Present Loop Error текушия ошибка
;* IntegH:IntegL				: Running Error Total
;* Ki						: Integral Gain factor коофициент инегрирования 

;* Output Variable = IntegH:IntegL 		: Integral Component. 
;выходные данные интегральная компонента

	movw	PaerrH:PaerrL,PrerrH:PrerrL	; Update Previous Error обнавляем приведущию ошибку

	lsl	PrerrL				; Multiply Error by 8 умножаем на 8
	rol	PrerrH
	lsl	PrerrL				
	rol	PrerrH
	lsl	PrerrL				
	rol	PrerrH

	add	IntegL,	PrerrL			; Add Result to Integral  добовляем результат в инегральную компоненту
	adc	IntegH,	PrerrH
	
;-----
Total:

;* Sums Proportional. Integral and Differential components
;складываем пропорциональную итегральную и диферинциальную компоненту

;* AccumH:AccumL =IntegH:IntegL + DeltaH:DeltaL +ProH:ProL * Kd

;* Input Variables:	IntegH:IntegL, PwmH:PwmL, DeltaH:DeltaL 

;* Output Variable:	AccumH:AccumL ;   Sum of Components.
;выходное значение сумма компонентов


	add	AccumL,	IntegL			; Add in the Integral добовляем дифиренциальную состовляющию 
	add	AccumH,	IntegH

	add	AccumL,	DeltaL			; Add in the Differential добавляем инегральную составляющию 
	add	AccumH,	DeltaH

	brpl	pc+3				; Total in  Sum Negative ? значение отрицательное?
					
	clr	AccumH				; Yes then Clear Sum Register ... если да то сбрасываем регистр суммы
	clr	AccumL
	
	lsr	AccumH				
	ror	AccumL
	lsr	AccumH				; Divide Sum by 8 делим на 8
	ror	AccumL
	lsr	AccumH
	ror	AccumL

	out	Ocr0A,	AccumL			; Update PWM Duty Cycle обновляем значение шим

	rjmp	Main


