$asm
$regfile "8535DEF.dat"

'----- Tabela Przeznaczenia rejestrow -----
'
'     r01   =  Rejestr do przechowywania danych (RAM)
'     r16   =  Rejestr Danych MAX5402
'     r17   =  Licznik Ogólnego Przeznaczenia 1
'     r18   =  Bufor 1 Klawiatury 4-przyciskowej
'     r19   =  Bufor 2 Klawiatury 4-przyciskowej
'     r20   =  Rejestr Wybranego potencjometru MAX5402
'     r21   =  Rejestr Danych LCD
'     r22   =  Rejestr Ogólnego Przeznaczenia
'     r23   =  Rejestr Ogólnego Przeznaczenia
'     r24   =  Rejestr Ogólnego Przeznaczenia
'     r25   =  Rejestr Ogólnego Przeznaczenia
'     r26   =  Rejestr Adresu w Pamięci I2C

      .def Ecc = R22
      .def Lcd_buf = R21
      .def Max_ch_buf = R20
      .def Max_da_buf = R16
      .def Count = R17
      .def Key_buf1 = R18
      .def Key_buf2 = R19
      .def Acc = R23
      .def I2cadr = R26
      .def Ram = R1

      .equ Rs = Pd7
      .equ Ena = Pd6
      .equ D4 = Pd5
      .equ D5 = Pd4
      .equ D6 = Pd3
      .equ D7 = Pd2
      .equ Scl = Pd0
      .equ Sda = Pd1
      .equ Rom_lcd = Portd

      .equ Lcd_cls = $01
      .equ Lcd_h = $02
      .equ Lcd_dir = $06
      .equ Lcd_sg_on = $40
      .equ Lcd_sg_off = $80
      .equ Lcd_shl = $10
      .equ Lcd_shr = $14
      .equ Lcd_4mod = $28
      .equ Lcd_curoff = $0c
      .equ Lcd_ini = $20




'======== Początek programu =========
Resetpr:
            cli
            ldi   Acc, $3e                                  'ustawienie stosu
            Out Sph , Acc
            ldi   Acc, $3d
            Out Spl , Acc

            'konfiguracja wejść/wyjść
            '1 - wyjście, 0 - wejście
            'Port klawiatury
            clr   Acc
            Out Ddra , Acc                                  'wejścia
            ser  Acc
            Out Porta , Acc                                 'Pull-Up
            Out Adcsr , Acc                                 'wyłaczenie A/C

            'Port MAXów
            ser Acc                                         'wyjscia
            Out Ddrc , Acc
            ser  Acc                                        'Pull-Up
            Out Portc , Acc

            'Port B - wolny
            clr Acc                                         'wejscia
            Out Ddrb , Acc
            clr  Acc                                        'wyzerowane
            Out Portb , Acc

            'Port LCD
            ser Acc                                         '#11111111
            Out Ddrd , Acc
            clr Acc                                         '#00000000
            Out Portd , Acc

            rcall Lcd_init                                  'inicjacja LCD

            rcall lcd_adr_cg                                'początek zapisuj znaków specialnych
            ldi   zl,   low(kreska1*2)
            ldi   zh,   high(kreska1*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            ldi   zl,   low(kreska2*2)
            ldi   zh,   high(kreska2*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            ldi   zl,   low(kreska3*2)
            ldi   zh,   high(kreska3*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            ldi   zl,   low(kreska4*2)
            ldi   zh,   high(kreska4*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            ldi   zl,   low(kreska5*2)
            ldi   zh,   high(kreska5*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            ldi   zl,   low(kreska6*2)
            ldi   zh,   high(kreska6*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            ldi   zl,   low(kreska7*2)
            ldi   zh,   high(kreska7*2)
            rcall lcd_prog                                  'zapisanie znaku specialnego
            rcall lcd_adr_dd                                'zakończenie definiowania znaków specialnych


            cbi   Rom_lcd, RS                               'zeruje sygnał RS
            cbi   Rom_lcd, Ena                              'zeruje sygnal ENA
            ldi   max_ch_buf, 0                             'zeruje rejestr potencjometru
            sbi   Rom_lcd, Sda                              'ustawia linie SDA
            sbi   Rom_lcd, Scl                              'ustawia linię SCL
            ldi   Max_ch_buf, 1                             'poczatkowa wartosc wybranego potecjometru
            ldi   Max_da_buf, 128                           'początkowa wartość potencjometru


'====== GŁÓWNA PĘTLA PROGRAMU ======'

Main:
            rcall lcd_clear                                 'czyszczenie wyświetlacza
            ldi   zl,   low(tablica*2)                      'wypisanie logo
            ldi   zh,   high(tablica*2)

            ldi   r25,   0                                  'zeruje licznik
         T1:
            Lpm                                             'odczyt z pamięci programu
            mov   lcd_buf, r0                               'przepisuje odczytany znak dp bufora LCD
            rcall lcd_wbyte                                 'wyświetlenie znaku
            adiw  zl,   1                                   'zwiększa adres w tablicy o jeden
            inc   r25                                       'zwiększa licznik wczytanych składników
            cpi   r25,   12                                 'sprawdza czy jest już osiem
            brne  T1

            rcall animacja                                  'wyswietla animacje kresek
      W1:
            rcall keyboard                                  'sprawdza stan klawiatury
            cpi   max_ch_buf, 1                             'czeka aż zostanie naciśnięte cokolwiek
            breq  w1                                        'jezeli nie nastąpiła zmiana to wraca

            rcall lcd_clear                                 'czyści LCD
            ldi   lcd_buf, 80                               'ustawia napis P:  V:
            rcall lcd_wbyte
            ldi   lcd_buf, 58
            rcall lcd_wbyte
            ldi   lcd_buf, 48
               add   lcd_buf, Max_ch_buf
            rcall lcd_wbyte
            ldi   lcd_buf, 32
            rcall lcd_wbyte
            ldi   lcd_buf, 86
            rcall lcd_wbyte
            ldi   lcd_buf, 58
            rcall lcd_wbyte
            ldi   lcd_buf, 32
            rcall lcd_wbyte
            rcall prescale

            ldi   Max_ch_buf, 1                             'w drugiej linii ustawia kreski
            rcall Repr                                      'na poziomach odpowiadających
            rcall lineset                                   'zapisanym wartościom w pamięci EEPROM
            ldi   Max_ch_buf, 2                             'ustawia aktywny drugi potencjometr
            rcall Repr                                      'odczytuje jego wartość z EEPROMU
            rcall lineset                                   'ustawia kreskę na poziomie wartości
            ldi   Max_ch_buf, 3
            rcall Repr
            rcall lineset
            ldi   Max_ch_buf, 4
            rcall Repr
            rcall lineset
            ldi   Max_ch_buf, 5
            rcall Repr
            rcall lineset
            ldi   Max_ch_buf, 6
            rcall Repr
            rcall lineset
            ldi   Max_ch_buf, 1
            rcall Repr

      W2:
            ldi   lcd_buf, 2                                'ustawienie kursora na LCD
            rcall lcd_xy                                    'na drugiej pozycji 1 linii
               ldi   Lcd_buf, 48
               add   Lcd_buf, Max_ch_buf                    'przeskalowanie liczby BIN na ASCI
            rcall lcd_wbyte                                 'wyświetl
            rcall prescale                                  'przeskalowanie wartości potencjometru
            rcall lineset                                   'ustawienie kreski na poziomie odp. jej wartości
            rcall keyboard                                  'sprawdza stan klawiatury

            rjmp w2



'====== KONIEC GŁÓWNEJ PĘTLI ======







'----- Procedury obsługi wyświetlacza LCD -----'

'--- Wartości przekazywane do buforów: ldi $wart = HEX; ldi wart=bin
'--- Procedura wysłania bajtu do LCD, wartosc w LCD_buf ---'
Lcd_wbyte:
            nop
            nop
            sbi   Rom_lcd, Rs
            rcall LCD_Port4

            ldi   count, 1
            rcall delay1us

            rcall LCD_Port4
            cbi   Rom_lcd, Rs
            ldi   count,   30
            rcall delay1us
            ret


Lcd_port4:
            cbi   rom_lcd, D4                               'zeruje cztery bity portu
            cbi   rom_lcd, D5
            cbi   rom_lcd, D6
            cbi   rom_lcd, D7
            sbrc  lcd_buf, 7                                'jeżeli bit 7 jest = 0 to przeskocz następną linię
            sbi   rom_lcd, D7
            sbrc  lcd_buf, 6
            sbi   rom_lcd, D6
            sbrc  lcd_buf, 5
            sbi   rom_lcd, D5
            sbrc  lcd_buf, 4
            sbi   rom_lcd, D4

            sbi   Rom_lcd, Ena                              'ustaw sygnał ENA
            ldi   count,   2
            rcall delay1us
            cbi   Rom_lcd, Ena                              'wyzeruj sygnał ENA

            lsl Lcd_buf                                     'przesuń 4 razy
            lsl Lcd_buf
            lsl Lcd_buf
            lsl Lcd_buf

            ret

Lcd_winstr:
            nop
            nop

            cbi   Rom_lcd, Rs
            rcall LCD_Port4                                 'wysłanie starszej terady

            ldi   count,   1
            rcall delay1us

            rcall LCD_Port4                                 'wysłanie młodszej tetrady
            ldi   count,   30
            rcall delay1us
            ret


'--- procedura czyszczenia LCD ---'
Lcd_clear:
           ldi   Lcd_buf, Lcd_cls                           'zaladowanie polecenia czyszczenia do bufora lcd
           rcall Lcd_winstr
           ldi acc,  5
           rcall delay1ms
           ret

'--- procedura ustawiania kursora w dowolnym miejscu ---'
Lcd_xy:
         ori  Lcd_buf, $80                                  'ustawienie kursora na odp. miejscu na wyświetlaczu
         rcall Lcd_winstr
         ret

'--- procedura wpisująca składniki definowanego znaku ---'
Lcd_prog:
            ldi   r25,   0                                  'zeruje licznik
         P1:
            Lpm                                             'odczyt z pamięci programu
            adiw  zl,   1                                   'zwiększa adres w tablicy o jeden
            mov   lcd_buf, r0                               'przepisuje odczytany znak dp bufora LCD
            rcall lcd_wbyte                                 'wyświetlenie znaku
            inc   r25                                       'zwiększa licznik wczytanych składników
            cpi   r25,   8                                  'sprawdza czy jest już osiem
            brne  P1

            ldi   Acc,  10
            rcall Delay1ms
            ret

'--- procedura ustawiająca Adres DD_RAM (normalne) ---'
Lcd_adr_dd:
         ldi   Lcd_buf, Lcd_sg_off                          'załadowanie polecenia włączenia znaków z tablicy ASCI
         rcall lcd_winstr
         ret

'--- procedura ustawiajaca adres CG-RAM (specialne) ---'
Lcd_adr_cg:
         ldi   Lcd_buf, Lcd_sg_on                           'załadowanie polecenia włączenie def. znaków specialnych
         rcall lcd_winstr
         ret

'--- procedura inicjująca wyświetlacz LCD - trybie 4 bitowym ---'
Lcd_init:
         ldi   Acc,  20
         rcall Delay1ms                                     'musi odczekać 16ms

         ldi   Lcd_buf, $3f                                 '00110000
         rcall Lcd_whalf
         ldi   Acc,  5
         rcall Delay1ms                                     'musi odczekać 5ms
         ldi   Lcd_buf, $3f                                 '00110000
         rcall Lcd_whalf
         ldi   Acc,   200
         rcall Delay1us                                     'musi odczekać 200us
         ldi   Lcd_buf, $3f                                 '00110000
         rcall Lcd_whalf
         ldi   Acc,  5
         rcall Delay1ms

         ldi   Lcd_buf, $2f                                 '00100000
         rcall Lcd_whalf

         ldi   Lcd_buf, Lcd_4mod
         rcall Lcd_winstr
         ldi   Lcd_buf, $08                                 'Display Off
         rcall Lcd_winstr
         ldi   Lcd_buf, $01                                 'Display On
         rcall Lcd_winstr
         ldi   acc,  5
         rcall delay1ms
         ldi   Lcd_buf, Lcd_dir                             'Display Dir
         rcall Lcd_winstr
         ldi   Lcd_buf, $0c                                 '0000 1100
         rcall Lcd_winstr
         ret

Lcd_whalf:
         nop
         nop

         cbi   Rom_lcd, Rs
         rcall LCD_Port4
         ldi   count,   20
         rcall delay1us
         ret




'----- Procedura opóźnienia 1us (mnożnik 1us w rejestrze Count) -----'
Delay1us:
            dec count
            cpi   count, 0
            brne Delay1us
            ret

'----- Procedura opóźnienia 1ms (mnożnik 1ms w Acc) -----'
Delay1ms:
            mov   r24, acc                                  'załaduj wartość Acc
         J1:
            ldi   Count, 250                                'załaduj do rej. Count wartość 250
            rcall Delay1us                                  'procedura opóźnienia o 1 mikrosekundę
            dec   R24                                       'zmniejsz wartość rej. R24
            cpi   R24, 0                                    'porównaj z zerem
            brne j1                                         'jeżeli nie zero to skacz do J1

            mov   r24, acc                                  'załaduj na nowo wartość do rej. R24
          J2:
             ldi   Count, 250
            rcall Delay1us
            dec   R24
            cpi   R24, 0
            brne j2

            mov   r24, acc
          J3:
             ldi   Count, 250
            rcall Delay1us
            dec   R24
            cpi   R24, 0
            brne j3

            mov   r24, acc
          J4:
             ldi   Count, 250
            rcall Delay1us
            dec   R24
            cpi   R24, 0
            brne j4
          ret

'----- Procedura późnienia 1s -----'
Delay1s:
         ldi   acc,  250
         rcall delay1ms
         ldi   acc,  250
         rcall delay1ms
         ldi   acc,  250
         rcall delay1ms
         ldi   acc,  250
         rcall delay1ms
         ret






Keyboard:
            'założenia DDRA = 0 (cały wejściowy), PortA = 255 (pull-up on)
            'zczytujemy wartość guzika z rejestru PINA
            'dekrementacja wyzerowanego rejestru powoduje wpisanie wart. 0FFh
            '| PA0 | PA1 | PA2 | PA3 |
            '|   P   |  D   |   L   |   G  |

            in    Key_buf1,   Pina                          'likwidacja
            ldi Acc , 10
            rcall delay1ms                                  'drgania
            in    Key_buf2,   Pina                          'stykow

            cp    Key_buf1, Key_buf2                        'jezeli sa
            brne  Keyboard                                  'rózne, to skok do początku
            cpi key_buf1, 255
            brne  key_id
            ldi   count,   200
            rcall delay1us
            rjmp keyboard


      Key_id:
            cpi   Key_buf1,   250                           '1111 1010
            breq  Key_hide
      Key_h:
            sbrs  Key_buf1,   0                             'nacisniety klawisz 'prawo'
            rjmp  Key_prawo
      Key_p:
            sbrs  Key_buf1,   2                             'naciśnięty klawisz 'lewo'
            rjmp  Key_lewo
      Key_l:
            sbrs  Key_buf1,   1                             'naciśnięty klawisz 'dół'
            rjmp  Key_dol
      Key_d:
            sbrs  Key_buf1,   3                             'naciśnięty klawisz 'góra'
            rjmp  Key_gora
      Key_g:
            ldi   acc,  120
            rcall delay1ms                                  'zaczekaj 120ms - asekuracyjnie
            ret


      '---- Potrzebne procedury ----'
      Key_prawo:
               inc   Max_ch_buf                             'zwieksz nr wybranego potencjometru
                  rcall Repr                                'odczytuje zapisaną wcześniej wartość
                  rcall Max_wbyte                           'zapisuje ustaloną nową wartość do potencjometru
               cpi   Max_ch_buf,  7                         'porownaj z wartoscia zabroniona 7
               breq  Key_1                                  'jeżeli wartosc jest = 0 to nadaj 6
               rjmp  Key_d
      Key_dol:
               dec   Max_da_buf
                  rcall Wepr                                'zapisuje ustaloną nową wartość do pamięci
               cpi   Max_da_buf,  0
               breq  Key_0
               rjmp  Key_d
      Key_lewo:
               dec   Max_ch_buf
                  rcall Repr                                'odczytuje zapisaną wcześniej wartość
                  rcall Max_wbyte                           'zapisuje ustaloną nową wartość do potencjometru
               cpi   Max_ch_buf,  0
               breq  Key_6
               rjmp  Key_l
      Key_gora:
               inc   Max_da_buf
                  rcall Wepr                                'zapisuje ustaloną nową wartość
               cpi   Max_da_buf,  255
               breq  Key_255
               rjmp  Key_g
      Key_255:
               ldi   Max_da_buf,  255
               rjmp  Key_g
      Key_6:
               ldi   Max_ch_buf,  6
               rcall Repr                                   'odczytuje zapisaną wcześniej wartość
               rjmp  Key_l
      Key_1:
               ldi   Max_ch_buf,  1
               rcall Repr                                   'odczytuje zapisaną wcześniej wartość
               rjmp  Key_d
      Key_0:
               ldi   Max_da_buf,  0
               rjmp  Key_d
      Key_hide:
               rcall lcd_clear                              'wyświetla UKRYTY tekst
               ldi   zl,   low(rights1*2)
               ldi   zh,   high(rights1*2)
               ldi   r25,   0                               'zeruje licznik
            K1:
               Lpm                                          'odczyt z pamięci programu
               mov   lcd_buf, r0                            'przepisuje odczytany znak dp bufora LCD
               rcall lcd_wbyte                              'wyświetlenie znaku
               adiw  zl,   1                                'zwiększa adres w tablicy o jeden
               inc   r25                                    'zwiększa licznik wczytanych składników
               cpi   r25,   12                              'sprawdza czy jest już osiem
               brne  K1

                  ldi   lcd_buf, $40
                  rcall lcd_xy

               ldi   zl,   low(rights2*2)
               ldi   zh,   high(rights2*2)
               ldi   r25,   0                               'zeruje licznik
            K2:
               Lpm                                          'odczyt z pamięci programu
               mov   lcd_buf, r0                            'przepisuje odczytany znak dp bufora LCD
               rcall lcd_wbyte                              'wyświetlenie znaku
               adiw  zl,   1                                'zwiększa adres w tablicy o jeden
               inc   r25                                    'zwiększa licznik wczytanych składników
               cpi   r25,   10                              'sprawdza czy jest już osiem
               brne  K2

               rcall Delay1s
               rcall Delay1s                                'czeka 2 sekundy

               rcall lcd_clear                              'przywraca napis na wyświetlaczu
               ldi   lcd_buf, 80                            'z poprawnymi wartościami
               rcall lcd_wbyte
               ldi   lcd_buf, 58
               rcall lcd_wbyte
               ldi   lcd_buf, 48
                  add   lcd_buf, Max_ch_buf
               rcall lcd_wbyte
               ldi   lcd_buf, 32
               rcall lcd_wbyte
               ldi   lcd_buf, 86
               rcall lcd_wbyte
               ldi   lcd_buf, 58
               rcall lcd_wbyte
               ldi   lcd_buf, 32
               rcall lcd_wbyte
               rcall prescale

               mov   Ram,  Max_ch_buf
               ldi   Max_ch_buf, 1
               rcall Repr
               rcall lineset
               ldi   Max_ch_buf, 2
               rcall Repr
               rcall lineset
               ldi   Max_ch_buf, 3
               rcall Repr
               rcall lineset
               ldi   Max_ch_buf, 4
               rcall Repr
               rcall lineset
               ldi   Max_ch_buf, 5
               rcall Repr
               rcall lineset
               ldi   Max_ch_buf, 6
               rcall Repr
               rcall lineset
               mov   Max_ch_buf, Ram
                  rcall Repr
               rjmp  Key_g




'----- PROCEDURY OBSŁUGI PAMIĘCI 24C02 -----'
'--- I2C_start ---'
I2cst:
          sbi   Rom_lcd, sda                                'SDA = 1
            ldi   count,   6
            rcall Delay1us                                  'opóznienie
         sbi   Rom_lcd, scl                                 'SCL = 1
            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         cbi   Rom_lcd, sda                                 'SDA = 0
            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         cbi   Rom_lcd, scl                                 'SCL = 0
            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         ret

'--- I2C_stop ---'
I2csp:
         cbi   rom_lcd, sda                                 'SDA = 0
            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         sbi   rom_lcd, scl                                 'SCL = 1
            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         sbi   rom_lcd, sda                                 'SDA = 1
            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         ret

'--- I2C_wbyte (bajt w rejestrze R25) ---'
I2cw:
         sbi   DDRD, sda                                    'ustawia SDA jako wyjście
         ldi   Ecc,  8                                      'będzie 8 bitów wysłanych
      I1:
         sbrs  R25,  7                                      'sprawdź czy bit 7 jest ustawiony
         cbi   rom_lcd, sda                                 'SDA = 0
         sbrc  R25,  7                                      'sprawdź czy bit 7 jest wyzerowany
         sbi   rom_lcd, sda                                 'SDA = 1

            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         sbi   rom_lcd, scl                                 'SCL = 1

            ldi   count,   6
            rcall Delay1us                                  'opóźnienie
         cbi   rom_lcd, scl                                 'SCL = 0

            ldi   count,   6                                'opóźnienie
            rcall Delay1us
         lsl   R25                                          'przesuń R25 o jeden w lewo
         dec   Ecc                                          'zmniejsz
         brne  I1                                           'jeśli R25 = 0 to idź dalej

            ldi   count,   6
            rcall Delay1us

         cbi   DDRD, sda                                    'ustawia SDA jako wejscie
         sbi   rom_lcd, sda                                 'sekcja ACK

            ldi   count,   6
            rcall Delay1us
         sbic   Pind, sda                                   'sprawdza czy wystąpiło potwierdzenie
            ori   Ecc,  1                                   'jezeli nie nastapilo potwierdzenie to wystaw komunikat o bledzie
         sbis  Pind, sda
            andi   Ecc, 0


            ldi   count,   6
            rcall Delay1us
         sbi   rom_lcd, scl                                 'SCL = 1

            ldi   count,   6
            rcall Delay1us
         cbi   rom_lcd, scl                                 'SCL = 0

            ldi   count,   6
            rcall Delay1us

         sbi   DDRD, sda                                    'ustawia SDA jako wyjście
         ret


'--- I2C_rbyte (bajt w rejestrze R25) ---'
I2cr:
         cbi   DDRD, sda                                    'ustawia SDA jako wejscie
         cbi   Rom_lcd, sda                                 'SDA = 0
            ldi   count,   6
            rcall Delay1us
         cbi   Rom_lcd, scl                                 'SCL = 0
            ldi   count,   6
            rcall Delay1us
         ldi   Ecc,  8                                      'będzie 8 bitów do wysłania
         clr   R25                                          'R25 = 00000000
      I3:
            ldi   count,   6
            rcall Delay1us
         lsl   R25                                          'przesuwa R25 o jeden w lewo
         sbi   rom_lcd, scl                                 'SCL = 1
         sbic  Pind, sda                                    'sprawdza czy na pinie SDA wystąpiło 0
         ori   R25,  1                                      'jezeli nie, to wpisuje 00000001 do R25
            ldi   count,   6
            rcall Delay1us
         cbi   rom_lcd, scl                                 'SCL = 0
         dec   Ecc                                          'zmniejsza licznik bitów
         cpi   Ecc,  0                                      'sprawdza czy 0
         brne  I3                                           'jak nie to jeszcze raz

            ldi   count,   6
            rcall Delay1us

         sbi   DDRD, sda                                    'ustawia SDA jako wyjscie
         sbi   rom_lcd, sda                                 'sekcja NO ACK
            ldi   count,   6
            rcall Delay1us
         sbi   rom_lcd, scl                                 'SCL = 1
            ldi   count,   6
            rcall Delay1us
         cbi   rom_lcd, scl                                 'SCL = 0
            ldi   count,   6
            rcall Delay1us

         mov   Max_da_buf,  R25                             'przepisz odczytaną wartość do Max_da_buf
         ret




'-----  EEPROM WRITE (adres = Max_ch_buf, dana = Max_da_buf) -----'
Wepr:
         rcall I2cst                                        'START
         ldi   R25,  160                                    'wpisanie adresu urządzenia 1010 0000
         rcall I2cw
            cpi   Ecc,  1
            breq  we1
         mov   R25,  Max_ch_buf                             'wpisanie adresu danej
         rcall I2cw
            cpi   Ecc,  1
            breq  we1
         mov   R25,  Max_da_buf                             'wpiasanie danej
         rcall I2cw
            cpi   Ecc,  1
            breq  we1
         rcall I2csp                                        'STOP


      We4:
         ldi   acc,   10                                    'opóźnienie 10ms
         rcall delay1ms
         ret

      We1:
         ldi   r25,  12                                     'jeżeli wystąpi błąd odbioru to wyświetl błąd 012
         rcall convert
         jmp   we4


'----- EEPROM READ (adres = Max_ch_buf, dana = Max_da_buf) -----'
Repr:
         rcall I2cst                                        'START
         ldi   R25,  160                                    'wpisanie adresu urządzenia 1010 0000
         rcall I2cw
         mov   R25,  Max_ch_buf                             'wpisanie adresu danej
         rcall I2cw
         rcall I2cst                                        'START
         ldi   R25,  161                                    'wpiasanie adresu urządzenia 1010 0001
         rcall I2cw
         rcall I2cr                                         'odczyt
         rcall I2csp                                        'STOP

         ldi   acc,   10                                    'opóźnienie 10us
         rcall delay1ms
         ret




'----- Procedura zapisu wartości do MAX5402 (wartość w Max_da_buf) -----

Max_wbyte:
            rcall Max_clk
            rcall max_select
            ldi   Ecc,  8                                   'ile razy już przesuneło
            mov   i2cadr,  Max_da_buf                       'nietypowe wykorzystanie rej. I2cadr

      Max_p1:                                               'pierwsza pętla w proced. MAX
            sbrs  i2cadr,  7
            rcall Max_0
            sbrc  i2cadr, 7
            rcall Max_1
               ldi   count,   2
               rcall Delay1us
            rcall Max_clk
            lsl   i2cadr

            dec   Ecc
            cpi   Ecc,  0
            brne  max_p1
               ldi   count,   2
               rcall Delay1us
            ldi   Ecc,  $fc                                 '1111 1100
            Out Portc , Ecc
               ldi   count,   2
               rcall Delay1us
            sbi   Portc,   0
            ret

      '---- Potrzebne podprocedury ----'
      Max_0:
            cbi   Portc, 1
               ldi   count,   2
               rcall Delay1us
            ret
      Max_1:
            sbi   Portc, 1
               ldi   count,   2
               rcall Delay1us
            ret
      Max_clk:
            sbi   Portc, 0
               ldi   count,   2
               rcall Delay1us
            cbi   Portc, 0
               ldi   count,   2
               rcall Delay1us
            ret



'----- Procedura wyboru pot. do zapisu -----
Max_select:
            ldi   acc,  $fb                                 '1111 1011
            mov   Count, Max_ch_buf
            Sec                                             '---<----   |CY|
         M2:
            dec   Count
            cpi   Count, 0
            breq  M1
            sec
            rol   acc
            rjmp  M2
         M1:
            andi  acc,  $fc                                 '1111 1100
            Out Portc , Acc
            ldi   count,   2
            rcall Delay1us
            ret


'----- Procedura zamiany wartości BIN na napis na LCD (dana w R25) -----'
Convert:
         ldi   lcd_buf, 48
         mov   Ram,  lcd_buf
         ldi   lcd_buf, 0
       B1:                                                  'ten fragment sprawdza ile setek mieści się w danej liczbie
         cpi   r25,  100
         brlo B2
         subi  R25,  100
         inc   Lcd_buf
         rjmp  B1
       B2:
         add   lcd_buf, ram
         rcall Lcd_wbyte
         ldi   lcd_buf, 0
       B3:                                                  'tutaj sprawdzana jest ilość dziesiątek
         cpi   r25,  10
         brlo  B4
         subi  R25,  10
         inc   Lcd_buf
         rjmp  B3
       B4:
         add   lcd_buf, ram
         rcall Lcd_wbyte
         ldi   lcd_buf, 0
       B5:                                                  'tutaj sprawdzana jest ilość jedności
         cpi   r25,  1
         brlo  B6
         subi  R25,  1
         inc   Lcd_buf
         rjmp  B5
       B6:
         add   lcd_buf, ram
         rcall lcd_wbyte
         ret


'----- Procedura obliczająca +/- i wartość <0...128> (wartość przeliczana w Max_da_buf) -----'
Prescale:
         mov   R25,  Max_da_buf
         cpi   R25, 128                                     'ustalenie znaku liczby
         breq  pr2
         brcs  pr1

         ldi   lcd_buf, 6                                   'liczba w plusie
         rcall lcd_xy
         ldi   lcd_buf, 43                                  'znak +
         rcall lcd_wbyte
         subi  R25, 128
         rcall convert                                      'liczba BIN zamieniona na ASCI
         rjmp  pr3

      Pr1:
         ldi   lcd_buf, 6                                   'liczba w minusie
         rcall lcd_xy
         ldi   lcd_buf, 45                                  'znak -
         rcall lcd_wbyte
         mov   Ram,  R25
         ldi   R25, 128
         Sub R25 , Ram
         rcall convert                                      'liczba BIN zamieniona na ASCI
         rjmp  pr3
      Pr2:
         ldi   lcd_buf, 6                                   'jeżeli liczba = 128 to nie wyświetla znaku
         rcall lcd_xy
         ldi   lcd_buf, 32                                  'znak spacji
         rcall lcd_wbyte
         ldi   R25,  0
         rcall convert                                      'liczba BIN zamieniona na ASCI
      Pr3:
         ret

'----- Procedura ustawiająca odpowiednią kreskę na odpowiedniej pozycji (wartości w Max_da_buf i Max_ch_buf)-----'
Lineset:
            'Max_ch_buf = która kreska
            'Max_da_buf = jak wysoko

            ldi   Lcd_buf, 68                               'przechodzi do drugiej linii LCD
            add   Lcd_buf, Max_ch_buf
            rcall Lcd_xy

            mov   Acc,  Max_da_buf                          'przepisuje wartość
            ldi   lcd_buf, 0
         Ls1:
            cpi  Acc,  128                                  'sprawdza czy liczba nie jest = 128
            breq  Ls3
            cpi   Acc,  40                                  'jak nie to odejmuje kolejne 40
            brlo  Ls2                                       '[tyle mniejwięcej wynosi skok kreski]'
            subi  Acc,  40
            inc   Lcd_buf
            rjmp  Ls1
         Ls2:
            rcall Lcd_wbyte
            rjmp  Ls4
         Ls3:
            ldi   lcd_buf, 3
            rcall lcd_wbyte
         Ls4:
            ret



'----- Procedura wyswietlajaca sinusoide -----'
Animacja:
            ldi   lcd_buf, $44
            rcall lcd_xy

            ldi   lcd_buf, 3
            rcall lcd_wbyte
            ldi   lcd_buf, 3
            rcall lcd_wbyte
            ldi   lcd_buf, 3
            rcall lcd_wbyte
            ldi   lcd_buf, 3
            rcall lcd_wbyte
            ldi   lcd_buf, 3
            rcall lcd_wbyte
            ldi   lcd_buf, 3
            rcall lcd_wbyte

            rcall delay1s
            rcall delay1s

            'pierwsza kreska na dół 2x
            ldi   lcd_buf, $44
            rcall lcd_xy
            ldi   lcd_buf, 2
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms
            ldi   lcd_buf, $44
            rcall lcd_xy
            ldi   lcd_buf, 1
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms

            'druga kreska na dół 3x
            ldi   lcd_buf, $45
            rcall lcd_xy
            ldi   lcd_buf, 2
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms
            ldi   lcd_buf, $45
            rcall lcd_xy
            ldi   lcd_buf, 1
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms
            ldi   lcd_buf, $45
            rcall lcd_xy
            ldi   lcd_buf, 0
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms

            'trzecia kreska na dól 1x
            ldi   lcd_buf, $46
            rcall lcd_xy
            ldi   lcd_buf, 2
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms


            'czwarta kreska do góry 1x
            ldi   lcd_buf, $47
            rcall lcd_xy
            ldi   lcd_buf, 4
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms

            'piąta kreska do góry 3x
            ldi   lcd_buf, $48
            rcall lcd_xy
            ldi   lcd_buf, 4
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms
            ldi   lcd_buf, $48
            rcall lcd_xy
            ldi   lcd_buf, 5
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms
            ldi   lcd_buf, $48
            rcall lcd_xy
            ldi   lcd_buf, 6
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms

            'szósta kreska do góry 2x
            ldi   lcd_buf, $49
            rcall lcd_xy
            ldi   lcd_buf, 4
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms
            ldi   lcd_buf, $49
            rcall lcd_xy
            ldi   lcd_buf, 5
            rcall lcd_wbyte
               ldi   acc,  200
               rcall delay1ms

            ret




'--- Tablica z napisem 'Digital Equ. ---'
Tablica:
         .db 68 , 105 , 103 , 105 , 116 , 97 , 108 , 32 , 69 , 113 , 117 , 46

'--- Tablica Copywrite ---'
Rights1:
         .db 75 , 114 , 122 , 121 , 122 , 97 , 110 , 105 , 97 , 107 , 32 , 80
Rights2:
         .db 50 , 48 , 48 , 54 , 45 , 48 , 52 , 45 , 48 , 49

'--- Tablice kresek reprezentujących poziomy suwaków ---'
Kreska1:
         .db 0 , 0 , 0 , 0 , 0 , 0 , 0 , 31
Kreska2:
         .db 0 , 0 , 0 , 0 , 0 , 0 , 31 , 0
Kreska3:
         .db 0 , 0 , 0 , 0 , 0 , 31 , 0 , 0
Kreska4:
         .db 0 , 0 , 0 , 0 , 31 , 0 , 0 , 0
Kreska5:
         .db 0 , 0 , 0 , 31 , 0 , 0 , 0 , 0
Kreska6:
         .db 0 , 0 , 31 , 0 , 0 , 0 , 0 , 0
Kreska7:
         .db 0 , 31 , 0 , 0 , 0 , 0 , 0 , 0
Kreska8:
         .db 31 , 0 , 0 , 0 , 0 , 0 , 0 , 0


$end Asm
End