;*************************************************** ; OLED Test I2C via USI-Interface ; MCU: ATMEL ATtiny2313 (ATtiny4313) ; Clock: 4 MHz ; I2C-PortB PB7=SCL; PB5=SDA ; ; Device slave address: $3C OLED ;ATtiny4313 memory use summary [bytes]: ;Segment Begin End Code Data Used Size Use% ;[cseg] 0x000000 0x00023c 556 16 572 4096 14.0% ;[dseg] 0x000060 0x000060 0 0 0 256 0.0% ;[eseg] 0x000000 0x000000 0 0 0 256 0.0% ; ; Rev.: 01042026 ;*************************************************** ; ; Assembler direktives: ; .nolist .include "tn4313def.inc" .list ; ; SRAM Definitions: ; .dseg ; Datasegment (SRAM) Start on .org 0x0060 ; address 0x0060 ; ; Constants definitions: .equ daten = portb .equ delay0 = 1000 .equ delay1 = 65535 ; ; Register definitions: .def inttemp = r12 ; backup register for Interrupt-Routines .def intreg = r14 ; backup register for SREG on ISRs .def temp = r16 ; universal register for arithmetics .def temp1 = r17 .def temp2 = r18 .def temp3 = r19 ; .cseg ; codesegment .org 0x0000 ; start address rjmp reset ; Interrupt vektors jump into addresses (default) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .org 0x0001 ; ext IRQ0 edge rjmp INT00 .org 0x0002 ; ext IRQ1 edge rjmp INT10 .org 0x0003 ; Timer 1 capt rjmp ICP10 .org 0x0004 ; Timer 1 comp match A rjmp OC100 .org 0x0005 ; Timer 1 overflow rjmp OVF10 .org 0x0006 ; Timer 0 overflow rjmp OVF00 .org 0x0007 ; UART Receive Complete rjmp URXC0 .org 0x0008 ; UART Data Register Empty rjmp UDRE0 .org 0x0009 ; UART Transmit Complete rjmp UTXC0 .org 0x000A ; Analog Comparator Interrupt rjmp ACI00 .org 0x000B ; Pin Change Interrupt Request B rjmp PCIBA .org 0x000C ; Timer 1 comp match B rjmp OC1BA .org 0x000D ; Timer 0 comp match A rjmp OC0AA .org 0x000E ; Timer 0 comp match B rjmp OC0BA .org 0x000F ; USI Start Condition rjmp USIST .org 0x0010 ; USI Overflow rjmp USIOV .org 0x0011 ; Eprom read ready rjmp ERDYA .org 0x0012 ; Watchdog Timer Overflow rjmp WDTAD .org 0x0013 ; Pin Change Interrupt Request A rjmp PCIAA .org 0x0014 ; Pin Change Interrupt Request D rjmp PCIDA ; ;Interrupt Service Routines - Interrupt Handler ;- - - - - - - - - - - - - - - - - - - - - - - - - INT00: ; ISR not in use reti INT10: ; ISR not in use reti ICP10: ; ISR not in use reti OC100: ; ISR not in use reti OVF10: ; ISR not in use reti OVF00: ; ISR not in use reti URXC0: ; ISR not in use reti UDRE0: ; ISR not in use reti UTXC0: ; ISR not in use reti ACI00: ; ISR not in use reti PCIBA: ; ISR not in use reti OC1BA: ; ISR not in use reti OC0AA: ; ISR not in use reti OC0BA: ; ISR not in use reti USIST: ; ISR not in use reti USIOV: ; ISR not in use reti ERDYA: ; ISR not in use reti WDTAD: ; ISR not in use reti PCIAA: ; ISR not in use reti PCIDA: ; ISR not in use reti ; reset: cli ; disable all interrupts ldi temp, low(ramend) ; Stackpointer setup out spl, temp ldi temp, high(ramend) out sph, temp rcall regclr ; register reset rcall portinit ; init I/O ports rcall I2Cmain ; I2C setup rcall oledinit ; OLED I2C init rcall oled_init1 ; OLED setup sei ; enable all interrupts rjmp main ; jump to main program ; regclr: ; set registers to zero clr inttemp clr intreg ldi temp, 0x00 ldi temp1, 0x00 ldi temp2, 0x00 ldi temp3, 0x00 ret ; portinit: ; definition I/O ports ldi temp, 0xFF ; PortB output I2C out ddrb, temp ; establish pullups out portb, temp out ddrd, temp ; PortD output ldi temp, 0xFF out portd, temp ret ; main: ; Main program rcall oled_line rcall wait1 rcall oled_line1 rcall wait1 rjmp endless ; endless: ; Endless loop rjmp endless ; oledinit: ; OLED I2C slave setup push temp rcall I2Cstart ldi temp, 0x78 ; slave start adresse + RW-Bit rcall I2C_out pop temp ret ; oled_init1: ; OLED initialization parameters push temp push temp1 push temp2 ldi temp, 0x00 ; OLED subsequential command mode rcall i2c_out ldi temp2, 0x00 ; clear address counter ldi ZL, LOW(table*2) ; load address of string into Z-pointer ldi ZH, HIGH(table*2) ; rcall print_0 ; function call "print_0" rcall wait2 pop temp2 pop temp1 pop temp ret ; ;************** ATtiny2313 ******************* print_0: lpm ; read table's first byte towards R0 mov temp, r0 ; testing R0 cpi temp, 0x0E ; breq print_end ; if "0x0E", then jump to "print_end" rcall i2c_out ; call oled output routine adiw ZL:ZH, 1 ; increment Z-pointer rjmp print_0 ; jump to start to take next byte ; ; from table ; ;************** ATtiny4313 ******************* ;print_0: ;lpm temp, z+ ; copy content of the Z-pointer adressed ; ; 16-bit-register to "temp" ;inc temp2 ; postincrement, address plus 1 ;cpi temp2, 0x0E ; readout table 14 times, ;breq print_end ; if 14, then jump to "print_end" ;rcall i2c_out ;rjmp print_0 ; jump to start to copy next byte ; print_end: rcall wait2 ret ; table: ; OLED parameters setup .db 0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40 .db 0x81, 0xCF, 0x8D, 0x14, 0xAF, 0x00, 0 ; ;- - - - Delay routines - - - - - - - ; wait1: rcall wait3 nop rcall wait3 nop rcall wait3 nop rcall wait3 nop ret ; wait2: ; delay loop 2: push yl ; save registers to stack... push yh push temp push temp1 push temp2 in temp2, SREG ; ...status register, too push temp2 ldi yl, low(delay0) ; load constant into 16 bit register ldi yh, high(delay0) ; using previous declared "delay0" rjmp repeatx ; jump to shared subroutine ; wait3: ; delay loop 3: push yl ; save registers to stack... push yh push temp push temp1 push temp2 in temp2, SREG ;...status register, too push temp2 ldi yl, low(delay1) ; load constant into 16 bit register ldi yh, high(delay1) ; using previous declared "delay1" rjmp repeatx ; jump to shared counter subroutine ; repeatx: ; 16 Bit subtracting routine: sbiw yl:yh, 1 ; decrements register pair brne repeatx ; counts to zero pop temp2 ; reestablish all on stack saved registers out SREG, temp2 pop temp2 pop temp1 pop temp pop yh pop yl ret ; ; TWI/I2C Routines via USI Interface (ATtiny2313/4313) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - I2Cmain: rcall I2Cinit rcall I2Cstart ldi temp, 0x78 ; address contains A0,A1,A2=GND + R/W-Bit (W=0; R=1) rcall I2C_out ;brts end ; if NACK (T-flag in SREG previous set to H), ret ; then jump to end ; ;end: ;rjmp endless ; I2Cinit: sbi portb, 7 ; SCL high sbi portb, 5 ; SDA high sbi ddrb, 7 ; PortB7 (SCL) configured as output sbi ddrb, 5 ; PortB5 (SDA) configured as output ldi temp, 0xFF out USIDR, temp ; fill up data register with ones completely ldi temp, 0x20 ; (1<no TWI clock out USICR,temp ret ; I2Cdown: clr temp out USICR, temp ; set off USI-function, PortB5, PortB7 use as normal ret ; I2Cstop: cbi portb, 5 ; SDA->L cbi USIDR, 7 ; data register MSB->L nop nop nop nop nop sbi portb, 7 ; SCL->H ; I2Cstop1: sbis pinb, 7 ; wait for SCL=H rjmp I2Cstop1 sbi portb, 5 sbi USIDR, 7 ; SDA->H ret ; I2Cstart: sbi portb, 5 ; SDA->H sbi USIDR, 7 ; data register MSB->H nop nop nop nop sbi portb, 7 ; SCL->H ; I2Cstart1: sbis pinb, 7 ; wait for SCL=H rjmp I2Cstart1 ; cbi USIDR, 7 ; data register MSB->L nop nop nop nop cbi portb, 7 ; SCL->L nop nop nop nop nop ret ; I2C_out: ; send slave's address together with R/W-Bit on temp push temp push temp1 out USIDR, temp ; addresse/data in data register ldi temp, 0xF8 ; reset USI-status register IR-Flags, counter on 8 out USISR,temp ; (1<H (USI clock toggle mode) ; I2C_out2: sbis pinb, 7 ; wait for SCL=H rjmp I2C_out2 nop nop nop nop sbi USICR, USITC ; SCL H->L (USI clock toggle mode) nop nop nop nop sbi USICR, USICLK ; shifting data register +1 and counter +1 nop dec temp1 ; counter for remaining bits left cpi temp1, 0x00 brne I2C_out1 ; loop, until reached zero ldi temp, 0xFF ; reset all flags in USI-status register out USISR, temp cbi ddrb, 5 ; SDA -> configured as input sbi USICR, USITC ; SCL L->H (USI clock toggle mode; read ACK/NACK) nop nop nop nop nop set ; set T-flag in SREG sbis pinb, 5 ; SDA already H (NACK)? clt ; no-> clear T-flag in SREG sbi USICR, USITC ; SCL H->L (USI clock toggle mode) sbi ddrb, 5 ; SDA reconfigured to output nop nop nop pop temp1 pop temp rcall wait2 ret ; oled_line: ; draw line push temp push temp1 ldi temp, 0x00 ; command mode subsequentially rcall i2c_out ldi temp, 0xB0 ; set page start address to 0 rcall i2c_out ldi temp, 0x00 ; Set Low Column Address to 0 rcall i2c_out ldi temp, 0x10 ; Set High Column Address to 0 rcall i2c_out rcall oledinit ; repeat OLED I2C init ldi temp, 0x40 ; graphic mode commands follow rcall i2c_out ldi temp1, 0x80 ; 128 pixel line_loop: ldi temp, 0xFF ; full pixel rcall i2c_out dec temp1 brne line_loop pop temp1 pop temp ret ; oled_line1: ; draw line push temp push temp1 ldi temp, 0x00 ; OLED subsequential command mode rcall i2c_out ldi temp, 0xB7 ; set page start address to end rcall i2c_out ldi temp, 0x00 ; set low column address rcall i2c_out ldi temp, 0x80 ; set high column address rcall i2c_out rcall oledinit ; repeat OLED I2C init ldi temp, 0x40 ; graphic mode commands follow rcall i2c_out ldi temp1, 0x80 ;128 pixel line_loop1: ldi temp, 0x01 rcall i2c_out dec temp1 brne line_loop1 pop temp1 pop temp ret ; ;*fin*