;*************************************************** ; OLED Test I2C via USI-Interface ; MCU: ATMEL ATtiny4313 ; Clock: 4 MHz (resp. STK500 clock) ; I2C-PortB PB7=SCL; PB5=SDA ; ; Device slave address: $3C OLED => 0x78 ;ATtiny4313 memory use summary [bytes]: ;Segment Begin End Code Data Used Size Use% ;[cseg] 0x000000 0x00027a 550 300 850 4096 20.8% ;[dseg] 0x000060 0x000060 0 0 0 256 0.0% ;[eseg] 0x000000 0x000000 0 0 0 256 0.0% ; Rev.: 05042026 ;*************************************************** ; ; 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 ; .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 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_mem_addr 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 ; 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, 0x10 ; read out table 16 times, breq print_end ; if 15, then jump to "print_end" rcall i2c_out rjmp print_0 ; jump to start to copy next byte ; print_end: rcall wait2 ret ; ; OLED parameters setup ; note: 0x81 and 0xC8, otherwise display mirrored table: .db 0xAE, 0xD5, 0x80, 0xA8, 0x3F, 0xD3, 0x00, 0x40 .db 0x81, 0xCF, 0xA1, 0xC8, 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 data/command to OLED via USI (I2C) push temp push temp1 out USIDR, temp ; address/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_mem_addr: ; Memory addressing mode rcall oledinit ; OLED-I2C-Init ldi temp, 0x00 rcall i2c_out ; ; set memory addressing mode ldi temp, 0x20 ; command 20hex rcall i2c_out ldi temp, 0x00 ; horizontal mode = 00hex rcall i2c_out ; ; set column address (0 -> 127) ldi temp, 0x21 ; command 21hex rcall i2c_out ldi temp, 0x00 ; set start row 0 rcall i2c_out ldi temp, 0x7F ; set end row 127 rcall i2c_out ; ; set page address (0 bis 7) ldi temp, 0x22 ; command 22hex rcall i2c_out ldi temp, 0x00 ; set start row 0 rcall i2c_out ldi temp, 0x7F ; set end row 127 rcall i2c_out ; ; send data rcall oledinit ; OLED-I2C-Init ldi temp, 0x40 ; pixel data follow rcall i2c_out ; ; call pixel font data table push temp push temp1 push temp2 ldi temp, 0x00 ; command mode rcall i2c_out ldi temp2, 0x00 ; clear address counter ldi ZL, LOW(font_tab*2) ; load address of string into Z-pointer ldi ZH, HIGH(font_tab*2) rcall print_1 ; function call "print_1" rcall wait2 pop temp2 pop temp1 pop temp ret ; print_1: lpm temp, z+ ; copy content of the Z-pointer adressed ; ; 16-bit-register to "temp" inc temp2 ; postincrement, address plus 1 cpi temp2, 0x00 ; read out table times, breq print_end1 ; if empty, then jump to "print_end1" rcall i2c_out rjmp print_1 ; jump to start to copy next byte ; print_end1: rcall wait2 ret ; font_tab: ; 5x7 font pixel .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x7F, 0x08, 0x08, 0x08, 0x7F ; H .db 0x20, 0x54, 0x54, 0x54, 0x78 ; a .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x38, 0x44, 0x44, 0x44, 0x38 ; o .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x7F, 0x08, 0x08, 0x08, 0x7F ; H .db 0x20, 0x54, 0x54, 0x54, 0x78 ; a .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x38, 0x44, 0x44, 0x44, 0x38 ; o .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x7F, 0x08, 0x08, 0x08, 0x7F ; H .db 0x20, 0x54, 0x54, 0x54, 0x78 ; a .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x38, 0x44, 0x44, 0x44, 0x38 ; o .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x7F, 0x08, 0x08, 0x08, 0x7F ; H .db 0x20, 0x54, 0x54, 0x54, 0x78 ; a .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x38, 0x44, 0x44, 0x44, 0x38 ; o .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x7F, 0x08, 0x08, 0x08, 0x7F ; H .db 0x20, 0x54, 0x54, 0x54, 0x78 ; a .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x00, 0x41, 0x7f, 0x40, 0x00 ; l .db 0x38, 0x44, 0x44, 0x44, 0x38 ; o .db 0x00, 0x07, 0x00, 0x07, 0x00 ; " .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space .db 0x00, 0x00, 0x00, 0x00, 0x00 ; space ; ;*fin*