/*
  Autor: Alberto J. Molina
  Última modificación: 22-09-12


  Se desea diseñar un programa para el ATMEGA328P que permita el control de
  un semáforo. En concreto, la luz verde debe estar activa durante 20s, la
  ámbar durante 5s y la roja durante 35s. Para ello, siga los siguientes pasos:
  a) Configure los piens PD0,1 y 2 como salidas. El pin PD0 controla la
  luz verde, el PD1 la ámbar y el PD2 la roja. Cada luz permanecerá encendida
  mientras el pin correspondiente está a 5v.
  b) Configure el timer para que genere una interrupción cada segundo sabiendo
  que la frecuenca de reloj del sistema, clk, es de 2Mhz.
  c) Programe e instale correctamente una rutina de servicio de interrrupción
  quer se encargue de ir incrementando la variable tiempo.
  d) Desarrolle el programa completo quer permita el funcionamiento del semáforo,
  haciendo un uso adecuado de la variable tiempO

*/

.include "m328pdef.inc"

/*************************************************************
	Incluimos un fichero de cabecera u otro dependiendo de si
	se ha definido el símbolo atmega328pa o no.
***************************************************************/



		.def	temporal=r16
		.def	tiempo = r18

		.equ	tiempo_verde = 20
		.equ	tiempo_ambar = 5
		.equ	tiempo_roja = 35


		.org	0
		jmp		Reset
		.org	$16	
		jmp		IntTimer1

			

/************************************************************
	PSEUDOCÓDIGO DEL PROGRAMA PRINCIPAL

	ConfiguraES();
	
	mientras (CIERTO)
		tiempo <-0
		PD0 <- 1
		PD1 <- 0
		PD2 <- 0
		mientras (tiempo < 20)
		fin mientras
		tiempo <- 0
		PD0 <- 0
		PD1 <- 1
		PD2 <- 0
		mientras (tiempo < 5)
		fin mientras
		tiempo <- 0
		PD0 <- 0
		PD1 <- 0
		PD2 <- 1
		mientras (tiempo < 35)
		fin mientras
	fin mientras
**************************************************************/


Reset:	
		rcall  ConfiguraES	;Configuramos la ES
	
Programa:
		;Luz verde
		clr	    tiempo
		sbi		portd,0
		cbi		portd,1
		cbi		portd,2
espera_ambar:
		cpi		tiempo,tiempo_verde
		brne	espera_ambar
		clr		tiempo
		;Luz ambar
		cbi		portd,0
		sbi		portd,1
		cbi		portd,0
espera_rojo:
		cpi		tiempo,tiempo_ambar
		brne	espera_rojo
		clr		tiempo
		;Luz roja
		cbi		portd,0
		cbi		portd,1
		sbi		portd,2
espera_verde:
		cpi		tiempo,tiempo_roja
		brne	espera_verde
		rjmp	Programa
		

Fin:	rjmp	Fin			;FIN



/*****************************************************************
RUTINA DE CONFIGURACIÓN DE LOS PUERTOS

PUERTOD
	-DDRD
			--------------------------------------------------
			|DDRD7|DDRD6|DDRD5|DDRD4|DDRD3|DDRD2|DDRD1|DDRD0|
			--------------------------------------------------
			DDRX = 1 (salida), 0(entrada)
	-PORTD
			---------------------------------------------------------
			|PORTD7|PORTD6|PORTD5|PORTD4|PORTD3|PORTD2|PORTD1|PORTD0|
			---------------------------------------------------------
			


TIMER
		;Con una frecuencia de 2Mhz, Prescaler 256 modo CTC y 
		;Ocr1a = 15625 obtenemos que el timer se pone a 0 cada 
		; 15625 x 0.5 us x 256 = 5ms  
		NO OLVIDAR ESCRIBIR PRIMERO EN LA PARTE ALTA 15625 = $3D09
		Registros usados:
		-OCCR1AH, OCCR1AL
		-TCCRIB
			-----------------------------------------------------
			| 0  |  0  |  0  |  0  | WGM12 | CS12 | CS11 | CS10 |
			-----------------------------------------------------
				WGM12 =>  1: Modo CTC ; 0: Modo Normal
				CS12:0 => Selección del Prescaler
						   --------------------------------
						   | 0  0  0  |  Parada	          |
						   | 0  0  1  |  clk	          |
						   | 0  1  0  |  clk/8            |
						   | 0  1  1  |  clk/64           |
						   | 1  0  0  |  clk/256          |
						   | 1  0  1  |  clk/1024         |
						   | 1  1  0  |  T1 flanco bajada |
						   | 1  1  1  |  T1 flanco subida |
						   --------------------------------
		- TCNT1H,TCNT1L
		- TIMSK1
			----------------------------------------------------------
			| -  |  -  |  0  |  -  |  -  |  -  |  0  | OCIE1 | TOIE1 |
			----------------------------------------------------------	
				OCIE1: Output compare interrupt enable
						0: Disable
						1: Enable
				TOIE1: Timer overflow interrupt enable
						0: Disable
						1: Enable

	PSEUDOCÓDIGO:
	sub ConfiguraES
		DDRD<- $7		;Pines PD[2:0] como salidas
		PORTD <- 0		;Apagamos inicialmente el semáforo
		OCR1A <- 15625	;Límite de comparación en 15625   
		TCCR1B <- 12 	;Prescaler 1 y modo CTC
		TCNT1 <- 0		;Contador a 0
		TIMSK1 <- 2		;Habilitación de la interrupción por comparación
		I <- 1			;Habilitar interrupción global
		
	fin ConfiguraES
******************************************************************/

ConfiguraES:
		
		ldi		temporal,7
		out		ddrd,temporal	;PINES PD2:0 COMO SALIDAS

		clr		temporal
		out		portd,temporal	;PORTD <- 0

		ldi		temporal, $3d
		sts		ocr1ah,temporal
		ldi		temporal, $09
		sts		ocr1al,temporal	;ocr1a = 15625

		ldi		temporal, 0b00001100 ; PPrescaler a 256 y modo CTC
		sts		tccr1b,temporal
	
		ldi		temporal,0
		sts		tcnt1h,temporal
		sts		tcnt1l,temporal	;Tcnt1 = 0


		ldi		temporal,2
		sts		timsk1,temporal	;Habilita interrupción del timer

		sei						;Habilita la generación de interrupciones.



		ret		



;****************************************************************
/*
	RUTINA DE INTERRUPCIÓN
		Tan sólo guarda el registro en pila y lo restaura
		No tiene otra tarea asociada

	PSEUDOCÓDIGO

	subrutinaint IntTimer1

		PILA <- SREG
		tiempo <- tiempo +1
		SREG <- PILA

	fin subrutina
																 */
;****************************************************************

IntTimer1:	
		in		temporal,sreg
		push	temporal

FinInt: inc		tiempo

		pop		temporal
		out		sreg,temporal		
		reti



