;
; hello8.video.asm
; Neil Gershenfeld CBA MIT 11/11/05
; RS170 hello-world
;

.include "tn13def.inc"
.equ rxpin = PB4; receive pin
.def syncB = R16
.def blackB = R17
.def temp = R18
.def temp1 = R19
.def tempTimer = R20
.def sync = R21
.def black = R22
.def rxbyte = R23
.def rxedbyte = R24
.def bitCount = R25
.def bitDelayCounter = R26
.def toWaste = R27
.def numCharsToGet = R28
.def iByte = R29
.def iByteB = R30
.def c_help = R31
.equ BIT_DELAY = 5
.equ INITIAL_BIT_DELAY = 7

.cseg
.org 0
rjmp reset

;brightnessmapPort:
;	.db 0b1110, 0b0100, 0b1110, 0b1011, 0b1001, 0b0001, 0b1010, 0b0011, 0b1100, 0b1111, 0b1111
;
;brightnessmapDD:
;	.db 0b0100, 0b0100, 0b0110, 0b1000, 0b0001, 0b0001, 0b1010, 0b0011, 0b1100, 0b0111, 0b1001

;	.db 0b01110010, 0b00100010, 0b01110110, 0b11010001, 0b10011000, 0b10001000, 0b01010101, 0b11001100, 0b00110011, 0b11111110, 0b11111001
map: ;dd first, then port
	.db 0b01110010, 0b00110010, 0b00100010, 0b00100010, 0b11110110, 0b11110110
	.db 0b11100110, 0b01110110, 0b11110001, 0b10110001, 0b10010001, 0b11111000 
	.db 0b11011000, 0b10011000, 0b11110101, 0b11001000, 0b10001000, 0b01110101 
	.db 0b11011100, 0b01010101, 0b11101100, 0b10110011, 0b11001100, 0b11111010 
	.db 0b10111010, 0b01110011, 0b11110111, 0b11101010, 0b10101010, 0b11111110, 
	.db 0b01110111, 0b01110111, 0b11111001, 0b11111001

;
; read from serial - as quick as possible, maintains state between calls
; assumes no line driver (doesn't invert bits)
; waiting states:
;	waiting for char:
;		bitCount = 9
;	waiting for next bit:
;		bitDelay > 0
;
; should take 18 instructions to call this function.
; 
GetChar:
	cpi bitCount, 9
	breq WaitingForChar
		;we're in a char
		cpi bitCount, 0
		breq FinishChar
		dec bitDelayCounter
		brne DoneGetChar7 ;when we get to target, we'll have used 7 instructions
			;read one more bit.
			;clc
			sbis PINB, rxpin ; if RX pin high skip
				sec ; otherwise set carry
			ror rxbyte ; otherwise shift bit into receive byte
			dec bitCount
			ldi bitDelayCounter, BIT_DELAY
			ret ; we have use 15 instructions, including final jump
	WaitingForChar:
		;we're not in a char yet
		cpi bitDelayCounter, 0
		brne WaitForEndOfChar
		sbis PINB, rxpin ;skip next if char started
			rjmp DoneGetChar8 ;used 8 instructions including final jump
		;else, we are starting a char
			dec bitCount
			ldi bitDelayCounter, INITIAL_BIT_DELAY
			nop
			nop
			nop
			nop
			ret ;used 9(15) instructsion including final jump
	WaitForEndOfChar:
		dec bitDelayCounter
		rjmp DoneGetChar9
	FinishChar:
		;rxbyte has char, finish and reset
		mov rxedByte, rxbyte
		ldi rxbyte, 0
		ldi bitCount, 9
		nop
		nop
		nop
		ret ;used 11(15) instructions after jump
	DoneGetChar6:
		nop
	DoneGetChar7:
		nop
	DoneGetChar8:
		nop
	DoneGetChar9:
		nop
		nop
		ret

;
; come here to waste time.
; time wasted is 3+(3*toWaste-1)+4 = 7 + 3*toWaste
; dont pass in 0
;
Waste:
	dec toWaste
	brne Waste
	nop
	ret

Waste7:
	ret

;
; GetChar called 4th cycle after GetChars.  
; free cycles afterwards = 33 - 6 = 27 cycles after return
; call is 3+51*numCharsToGet-1+20+4 = 51*n-1 + 27 = 51*n - 24
;
GetChars:
	rcall GetChar
	dec numCharsToGet
	brne KeepGettingChars
		;we're done.
		ret
	KeepGettingChars:
		;wait and get another
		ldi toWaste, 6 ; 6*3+7 = 25
		nop
		nop
		rcall Waste 
		rjmp GetChars


; we shall call GetChar every 51 cycles, so 33 instructions between calls.
OutputSync:
	out PORTB, black ;5 us (48c) to waste before bringing pin back up ;1
	out DDRB, blackB ;;;
	rcall GetChar ;now we have 30 instructions to waste before bringing pin back up, 33 before GetChar ;2
	ldi toWaste, 6 ; 6*3+7 = 25 ;20
	rcall Waste ;21
	nop ;46
	nop ;47
	ldi numCharsToGet, 11; takes 11*51-24 = 537 operations ;48
	out PORTB, sync ;now must waste 58.55us, (562c) ;49
	out DDRB, syncB ;;;
	rcall GetChars ;50
	nop ;587
	ret; ret guy has 27-4-3-1 = 19 cycles to me again for serial, 610-587-4-3=16 to call again for sync;588


OutputLine:
	out PORTB, sync ;5 us (48c) to waste before bringing pin back up ;1
	out DDRB, syncB ;;;
	rcall GetChar ;now we have 30 instructions to waste before bringing pin back up, 33 before GetChar ;2
	ldi toWaste, 6 ; 6*3+7 = 25 ;20
	rcall Waste ;21
	nop ;46
	nop ;47
	nop ;48
	out PORTB, black ;now must waste 5us (48c) ;49
	out DDRB, blackB ;;;
	nop ;
	nop ;
	nop ;52
	rcall GetChar ;53
	ldi toWaste, 6 ; 6*3+7 = 25 ;70
	rcall Waste ;71
	nop ;95
	ldi numCharsToGet, 9; takes 9*51-24 = 435 operations ;96
	;out PORTB, black ;97
	;out DDRB, blackB ;;;
	out PORTB, iByte ;97
	out DDRB, iByteB ;;;
	rcall GetChars ;98
	out PORTB, black ;533
	out DDRB, blackB ;;;
	ldi toWaste, 6 ; 6*3+7 = 25 ;534
	rcall Waste ;535
	rcall GetChar ;560
	nop ;578
	rcall Waste7 ;579
	nop ;586
	nop ;587
	ret; ret guy has 27-4-3-1 = 19 cycles to me again for serial, 610-587-4-3=16 to call again for sync;586

OutputBlack:
	out PORTB, sync ;5 us (48c) to waste before bringing pin back up ;1
	out DDRB, syncB ;;;
	rcall GetChar ;now we have 30 instructions to waste before bringing pin back up, 33 before GetChar ;2
	ldi toWaste, 6 ; 6*3+7 = 25 ;20
	rcall Waste ;21
	nop ;46
	nop ;47
	ldi numCharsToGet, 11; takes 11*51-24 = 537 operations ;48
	out PORTB, black ;now must waste 58.55us, (562c) ;49
	out DDRB, blackB ;;;
	rcall GetChars ;50
	out PORTB, black ;587
	out DDRB, blackB ;;;
	ret; ret guy has 27-4-3-1 = 19 cycles to me again for serial, 610-587-4-3=16 to call again for sync;588

;
; main program
;
reset:
	ldi temp, low(RAMEND) ; set stack pointer to top of RAM
	out SPL, temp ;
	;ldi temp, 0x7f ; maximum RC clock
	;out OSCCAL, temp
	ldi temp, (1 << CLKPCE) ; set clock divider
	ldi temp1, (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0) ; /1
;	ldi temp1, (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (1<<CLKPS0) ; /2
;	ldi temp1, (0<<CLKPS3) | (0<<CLKPS2) | (1<<CLKPS1) | (0<<CLKPS0) ; /4
;	ldi temp1, (0<<CLKPS3) | (0<<CLKPS2) | (1<<CLKPS1) | (1<<CLKPS0) ; /8
	out CLKPR, temp ;
	out CLKPR, temp1 ;
	in temp, MCUCR ;disable pullups
	ori temp, PUD
	out MCUCR, temp
	sbi DDRB, PB0 ; output on DAC bits
	sbi DDRB, PB1 ; 
	sbi DDRB, PB2 ;
	sbi DDRB, PB3 ; 
	;ldi one, 1
	ldi black, 0b1110
	ldi blackB, 0b0100
	mov iByte, black
	mov iByteB, blackB
	;ldi white, 0b11
	ldi sync, 0b0000
	ldi syncB, 0b1111
	ldi bitCount, 9
	ldi c_help, 2
	ldi zl,low(map*2)
	ldi zh, high(map*2)
	ldi tempTimer, 2
	
	;mov rxedByte, white
	loopUp1:
	nop
	nop
	nop
	loopUp:
	loop:
	;242 image lines
	ldi temp, 242
	image_loop:
		rcall OutputLine
		ldi toWaste, 10; 10*3+7=37
		rcall Waste
		dec temp
	brne image_loop
	ldi temp, 5
	black_loop:
		rcall OutputBlack
		ldi toWaste, 10; 10*3+7=37
		rcall Waste
		dec temp
	brne black_loop
	ldi temp, 3
	sync_loop:
		rcall OutputSync
		ldi toWaste, 10; 10*3+7=37
		rcall Waste
		dec temp
	brne sync_loop
	ldi temp, 11
	black_loop2:
		rcall OutputBlack
		ldi toWaste, 10; 10*3+7=37
		rcall Waste
		dec temp
	brne black_loop2
	rcall OutputBlack
	;ldi zl,low(map*2)
	;add zl, c_help
	;lpm iByte, Z
	;mov c_help, rxedbyte

	dec c_help;-
	brne MMM;-
		ldi c_help, 31;-	
	MMM:;-
	mov temp1, c_help
	;cpi c_help, 31
	;brlo DoIt
	;	ldi temp1, 62
	;	sub temp1, c_help 
	;DoIt:
	;mov iByte, rxedbyte
	ldi zl, low(map*2)
	ldi zh, high(map*2)
	;adiw zh:zl, 30
	add zl, rxedbyte
	brcc Next
		inc zh
	Next:
	lpm iByte, Z
	mov iByteB, iByte
	lsr iByteB
	lsr iByteB
	lsr iByteB
	lsr iByteB
	andi iByte, 0b00001111
	;ldi toWaste, 4; 4*3+7 = 19
	;rcall Waste
	;dec tempTimer
	;brne loopUp1
	;ldi tempTimer, 3
	;dec c_help
	;brne loopUp
	;ldi c_help, 62
	rjmp loop

	
	
	
	
	