Home‎ > ‎Freeware‎ > ‎Decoder Accessori Open Source‎ > ‎

Gestione delle CV


A questo punto vengono inserite le routines per la gestione delle CV (scrittura e verifica/lettura). La lettura delle CV puo' essere fatto in "direct mode" consentendo l'accesso diretto a tutte le 10 CV utili per il funzionamento del decoder. La lista delle CV e' riportata in questa tabella:

 CV Nome Default Utilizzo
 CV1 Indirizzo LSB
 1 Parte meno significativa dell'indirizzo del decoder. L'indirizzo completo si ottiene dalla formula:
 Indirizzo = CV1 + 64*CV9
 CV3 Periodo OUT 1 e 2
 0 Periodo in decine di ms per il periodo di attivazione delle uscite:
 0: Uscita attiva in modo indefinito
 1: 10ms
 2: 20ms
 ...
 255: 2550 ms
 CV4 Periodo OUT 3 e 4
 0 Come sopra per le uscite 3 e 4
 CV5 Periodo OUT 5 e 6
 0 Come sopra per le uscite 5 e 6
 CV6 Periodo OUT 7 e 8
 0 Come sopra per le uscite 7 e 8
 CV7 Versione del decoder
 10 Versione del decoder: 1.0
 CV8 Costruttore 13 Decoder DIY (autocostruito - OPEN SOURCE). Scrivendo un qualsiasi valore in questa CV si otterra' il reset dei valori della CV al default.
 CV9 Indirizzo MSB
 0 Parte piu' significativa dell'indirizzo del decoder. L'indirizzo completo si ottiene dalla formula:
 Indirizzo = CV1 + 64*CV9
 CV10 Modo di Funzionamento
 0 Funzionamento del decoder con le diverse stazioni di comando:
 0: Funzionamento DCC standard
 1: Funzionamento adatto a Multimaus ROCO
 2: Funzionamento adatto a Intellibox Uhlenbrock


La routine di lettura e scrittura delle CV permette l'accesso sia a byte sia a bit permettendo in quest'ultimo modo di velocizzare le operazioni di lettura / verifica.

La CV10 permette di settare il funzionamento del decoder a fronte del comportamento di alcune delle piu' diffuse centraline in commercio, cioe' il ROCO Multimaus e Uhlenbrock Intellibox. Questa CV permette di adeguarsi a questi diversi metodi di comando:

 CV10=0 Questo e' il modo di funzionamento standard come scritto nelle norme NMRA: le uscite vengono attivate a fronte di un comando di "set output" del tipo:

10AAAAAA // 1AAA1DDD // EEEEEEEE dove A e' l'address e D e' l'uscita da attivare

e disattivate a fronte di un segnale di "reset output" del tipo:

10AAAAAA // 1AAA0DDD // EEEEEEEE dove A e' l'address e D e' l'uscita da disattivare

 CV10=1
 Modo di compatibilita' con Multimaus:
 Il Multimaus nel momento che l'utente attiva un accessorio inizia ad inviare a raffica pacchetti di attivazione fino a quando non viene rilasciato il tasto al che invia un unico comando di disattivazione.
Il firmware in questo caso considera un solo comando di attivazione tra il primo pacchetto "set output" arrivato e quello finale di "reset output", permettendo una durata esatta nelle uscite "impulsive" anche se si tiene il tasto premuto a lungo. Nel caso l'uscita sia indefinitamente attivata si ha un comportamento "toggle" cioe' a successive attivazioni dell'uscita si hanno successivi periodi di ON/OFF.

Nel caso si setti questa CV a 0 il funzionamento con Multimaus sara' con l'uscita attivata fino a che il tasto e' premuto, poi sara' disattivata, i tempi di attivazione delle CV3-CV6 non saranno considerati
 CV10=2 Modo di compatibilita' con Intellibox:
 L'Intellibox invia una sequenza di pacchetti di attivazione (della durata di circa 1 secondo) ogni volta che si preme un tasto del tastierino e non invia mai la disattivazione dell'uscita.
Il firmware in questo caso considera un solo comando di attivazione tra il primo pacchetto "set output" arrivato accorpandolo con quelli piu' vicini di 200ms, permettendo una durata esatta nelle uscite "impulsive". Nel caso l'uscita sia indefinitamente attivata si ha un comportamento "toggle" cioe' a successive attivazioni dell'uscita si hanno successivi periodi di ON/OFF.

Nel caso si setti questa CV a 0 nel funzionamento con Intellibox sara' impossibile disattivare le uscite con periodo indefinito (cioe' con CV3-CV6=0). Le attivazioni delle uscite in generale saranno allungate di circa 1 secondo.


Ecco di seguito il listato completo del programma per il decoder open source:



program OSD

'===============================================================================
'===============================================================================
' ASSEGNAZIONE DEI PIN per il PIC 16F628A
'===============================================================================
'===============================================================================
'                _____  _____
'         ACK  -|RA2  --  RA1|- OUT4
'              -|RA3      RA0|- OUT3
'              -|RA4      RA7|- OUT1
'         MCLR -|RA5      RA6|- OUT2
'         GND  -|VSS      VDD|- +5V
'         DCC  -|RB0      RB7|- OUT7
'              -|RB1      RB6|- OUT8
'              -|RB2      RB5|- OUT6
'         LED  -|RB3      RB4|- OUT5
'                ------------


'===============================================================================
'===============================================================================
' ASSEGNAZIONE DELLE VARIABILI
'===============================================================================
'===============================================================================

dim  state as byte                                                              ' variabile di stato per la fsm che riconosce il DCC:
                                                                                ' 0:attesa preambolo,
                                                                                ' 1:load byte,
                                                                                ' 2:riconoscimento stop/start bit
                                                                                ' 3:pacchetto arrivato in attesa di decodifica
dim one_count as byte                                                           ' numero di bit "1" nel preambolo
dim bit_count as byte                                                           ' cantatore per gli 8 bit del byte da caricare
dim point as byte                                                               ' punta all'elemento dell'array che contiene l'ultimo byte DCC ricevuto
dim d0,d1,d2,d3 as byte                                                         ' variabili che contengono il pacchetto DCC (interrupt)
dim x0,x1,x2,x3 as byte                                                         ' variabili che contengono il pacchetto DCC (decodifica)
dim pack_len as byte                                                            ' lunghezza del pacchetto durante la decodifica
dim ok as byte                                                                  ' Se OK=0 allora il pacchetto ha il checksum OK
dim i,j,tmp as byte                                                             ' controllo dei loop e appoggio generico
dim ledco as byte                                                               ' controllo del LED
dim address as word                                                             ' indirizzo del decoder ricavato dal pacc. DCC
dim cvaddl,cvaddh as byte                                                       ' parti bassa e alta dell'indirizzo
dim cvadd as word                                                               ' indirizzo del decoder ricavato dalle CV
dim reset_out as byte                                                           ' Flag per resettare le uscite
dim uscite as byte                                                              ' Questo e' il controllo delle stato delle 8 uscite
dim mask as byte                                                                ' Variabile di appoggio
dim service as byte                                                             ' se 1 siamo in Service Mode
dim cmd_set,cmd_reset as byte                                                   ' Set o reset delle singole uscite
dim count1,count2,count3,count4,count5,count6,count7,count8 as byte             ' Conteggio del tempo di attivazione per le uscite
dim count_cv3,count_cv4,count_cv5,count_cv6 as byte                             ' CV con il tempo di attivazione per le diverse uscite
dim setmode as byte                                                             ' CV che controlla il modo di set e reset delle uscite
                                                                                ' 0: DCC standard
                                                                                ' 1: Multimaus
                                                                                ' 2: Intellibox
dim setout as byte                                                              ' comando di attivazione delle uscite modo MMAUS
dim ctrlco as byte                                                              ' timeout per attivazione delle uscite modo IBX
dim lastcom as byte                                                             ' Ultimo comando ricevuto nel modo IBX


'===============================================================================
'===============================================================================
' ROUTINE DI INTERRUPT per LA DECODIFICA DCC
'===============================================================================
'===============================================================================

sub procedure interrupt

  INTCON.INTF=0                                                                 ' fai ripartire il controllo dell'interrupt sul pin "INT"
 
  if OPTION_REG.INTEDG then                                                     ' se c'e' un fronte in salita allora...
    OPTION_REG.INTEDG=0                                                         ' predisponi per aspettare un fronte in discesa
    TMR0=176                                                                    ' setta il TIMER0 a 176 in modo vada in overflow dopo 80us
    INTCON.T0IF=0                                                               ' resetta il flag di overflow per Timer0
  else
    OPTION_REG.INTEDG=1                                                         ' se c'e' un fronte in discesa allora...
    if INTCON.T0IF=0 then                                                       ' se non c'e' overflow di Timer0 allora e' un "1"...

      select case state                                                         ' macchina a stati finiti

        case 0                                                                  ' STATO 0: attesa di un preambolo. Se arriva un "1"...
          if one_count<>10 then
            inc(one_count)                                                      ' ... incrementa il numero di "1" fino a un massimo di 10
          end if

        case 1                                                                  ' STATO 1: shift i byte del pacchetto e introduci un "1"
          select case point
            case 0
              d0=(d0 << 1)+1
            case 1
              d1=(d1 << 1)+1
            case 2
              d2=(d2 << 1)+1
            case 3
              d3=(d3 << 1)+1
          end select
          inc(bit_count)                                                        ' incrementa il numero di bit
          if (bit_count=8) then                                                 ' se e' finito il byte,
            state=2                                                             ' se e' un byte intero, check se il pacchetto e' finito
          end if
         
        case 2                                                                  ' STATO 2: il byte e' finito, check della fine pacchetto
          bit_count=0                                                           ' resetta il contatore dei bit...
          state=3                                                               ' "1" dopo la fine del byte => il pacchetto e' finito
      end select
     
    else
                                                                                ' altrimenti se c'e' overflow di Timer0 e' uno "0"
      select case state                                                         ' macchina a stati finiti

        case 0                                                                  ' STATO 0: attesa del bit di start. Se arriva uno "0"...
          if one_count=10 then
            state=1                                                             ' se sono arrivati almeno 10 bit a "1" allora inizio pack
          end if
          one_count=0                                                           ' in ogni caso azzera il conteggio degli "1"

        case 1                                                                  ' STATO 1:shift i byte del pacchetto e introduci uno "0"
          select case point
            case 0
              d0=(d0 << 1)
            case 1
              d1=(d1 << 1)
            case 2
              d2=(d2 << 1)
            case 3
              d3=(d3 << 1)
          end select
          inc(bit_count)                                                        ' incrementa il numero di bit
          if (bit_count=8) then                                                 ' se e' finito il byte,
            state=2                                                             ' se e' un byte intero, check se il pacchetto e' finito
          end if

        case 2                                                                  ' STATO 2: il byte e' finito, check fine pacchetto
          bit_count=0                                                           ' resetta il contatore dei bit...
          inc(point)                                                            ' e passa al prossimo byte
          if (point=4) then                                                     ' Se il pacchetto e' troppo lungo, consideralo arrivato
            state=3
          else
            state=1                                                             ' Se non e' troppo lungo allora shifta il prossimo byte
          end if
      end select

    end if
  end if

end sub


'===============================================================================
'===============================================================================
' Impulso di acknowledge
'===============================================================================
'===============================================================================

sub procedure acknowledge

  PORTA.2=1
  delay_ms(6)                                                                   ' Impulso di 6ms sulla linea di acknowledge
  PORTA.2=0

end sub


'===============================================================================
'===============================================================================
' INIZIALIZZA LE CV
'===============================================================================
'===============================================================================

const cvdef as byte[10] = ( 1,                                                  ' CV1 - parte bassa dell'indirizzo decoder
                            0,                                                  ' CV2 - non usata
                            0,                                                  ' CV3 - periodo di attivazione dell'uscita 1 e 2
                            0,                                                  ' CV4 - periodo di attivazione dell'uscita 3 e 4
                            0,                                                  ' CV5 - periodo di attivazione dell'uscita 5 e 6
                            0,                                                  ' CV6 - periodo di attivazione dell'uscita 7 e 8
                           10,                                                  ' CV7 - contiene la versione del decoder (1.0)
                           13,                                                  ' CV8 - contiene il costruttore (Open Source - DIY)
                            0,                                                  ' CV9 - parte alta dell'indirizzo decoder
                            0)                                                  ' CV10 - modo di funz. (0:STD,1:MMAUS,2:IBX)


sub procedure inizializza_CV

  for i=0 to 9
    eeprom_write(i,cvdef[i])                                                    ' Scrivi il valore di default per le 10 CV
  next i

end sub


'===============================================================================
'===============================================================================
' LEGGI LE CV
'===============================================================================
'===============================================================================

sub procedure leggi_CV

  do loop until EECON1.WR=0                                                     ' E' finita una scrittura precedente?

  for i=0 to 9
    tmp=eeprom_read(i)                                                          ' Leggi il valore delle 10 CV
    select case i
      case 0 cvaddl=tmp                                                         ' indirizzo parte bassa
      case 2 count_cv3=tmp                                                      ' periodo delle uscite 1 e 2
      case 3 count_cv4=tmp                                                      ' ...
      case 4 count_cv5=tmp                                                      ' ...
      case 5 count_cv6=tmp                                                      ' ...
      case 8 cvaddh=tmp                                                         ' indirizzo parte alta
      case 9 setmode=tmp                                                        ' modo di funzionamento
    end select
  next i
  cvadd=(cvaddl and 0x3F) + ((cvaddh and 0x7) << 6)                             ' indirizzo completo del decoder

end sub


'===============================================================================
'===============================================================================
' Lettura e scrittura delle CV in "Direct Mode"
'===============================================================================
'===============================================================================

sub procedure CV_management

  if (x0 and 0x3)=0 then                                                        ' decodifica le cv agli address 1..128
    x1=x1 and 0x7F                                                              ' considera solo i 7 bit di indirizzo (0..127)
    j =(x0  and 0x0C) >> 2                                                      ' decodifica il codice dell'istruzione da eseguire

    select case j

      case 1                                                                    ' "1" verifica CV
        tmp=eeprom_read(x1)                                                     ' leggi la CV all'indirizzo di eeprom (cv addr-512)
        if (tmp=x2) then
          acknowledge                                                           ' se e' uguale a quella inviata allora ACKnowledge
        end if

      case 2                                                                    ' "2" Operazioni sui singoli BIT
     
        if x2.4=1 then                                                          ' QUI si scrive un bit=========================
          tmp=eeprom_read(x1)                                                   ' leggi tutta la CV
          mask=1 << (x2 and 0x7)                                                ' Seleziona il bit da scrivere
          if x2.3=0 then
            tmp=tmp and not(mask)                                               ' se si deve scrivere 0
          else
            tmp=tmp or mask                                                     ' se si deve scrivere 1
          end if
          eeprom_write(x1,tmp)                                                  ' Scrivi la CV modificata
          if x1=7 then
            inizializza_CV                                                      ' Se era la CV8 allora resetta i valori al default
          end if
          acknowledge                                                           ' Impulso di acknowledge
          leggi_CV                                                              ' Rileggi le CV
         
        else                                                                    ' QUI si verifica un BIT=========================
          tmp=eeprom_read(x1)                                                   ' Leggi la CV
          mask=1 << (x2 and 0x7)                                                ' Seleziona il bit giusto
          if ((tmp and mask)<>0) and (x2.3=1) then
            acknowledge                                                         ' Se il bit e' 0 e viene confrontato con 0 -> ACK
          end if
          if ((tmp and mask)=0) and (x2.3=0) then
            acknowledge                                                         ' Se il bit e' 1 e viene confrontato con 1 -> ACK
          end if
        end if

      case 3                                                                    ' "3" Scrivi la CV
        eeprom_write(x1,x2)                                                     ' Scrivi
        if x1=7 then
          inizializza_CV                                                        ' se stiamo scrivendo nella CV8 allora inizializza le CV
        end if
        acknowledge                                                             ' ACK
        leggi_CV                                                                ' rileggi tutte le cv utili al funzionamento
         
    end select

  end if

end sub


'===============================================================================
'===============================================================================
' DECODIFICA IL PACCHETTO IN ARRIVO
'===============================================================================
'===============================================================================

sub procedure decodifica

  pack_len=point                                                                ' salva la lunghezza del pacchetto
  x0=d0                                                                         ' copia il pacchetto
  x1=d1
  x2=d2
  x3=d3
  point=0                                                                       ' ripristina le variabili per acquisire un nuovo pacchetto
  state=0                                                                       ' riparti per l'acquisizione del prossimo pacchetto

  select case pack_len                                                          ' controllo per il byte di controllo
    case 2
      ok=x0 xor x1 xor x2                                                       ' per pacchetti di 3 byte
    case 3
      ok=x0 xor x1 xor x2 xor x3                                                ' e per pacchetti di 4 byte
    case else
      ok=1                                                                      ' negli altri casi non si decodifica
  end select
 
  if ok=0 then                                                                  ' Se il pacchetto e' corretto allora...
 
    select case pack_len

      case 2                                                                    ' decodifica i pacchetti da 3 bytes====================

        if (x0=0x0) and (x1=0x0) then                                           ' Questo e' il pacchetto di RESET
          reset_out=1                                                           ' "sospendi" tutti gli output
          cmd_reset=0xFF                                                        ' resetta tutte le uscite
          service=0                                                             ' Non siamo in service
          ledco=1                                                               ' spegni il LED per 10msec
        end if

        if (x0=0xFF) and (x1=0x0) then                                          ' Questo e' l'IDLE
          service=0                                                             ' Non siamo in service
        end if

        if ((x0 and 0xC0)=0x80) and ((x1 and 0x80)=0x80) then                   ' Pacchetto per accessori standard
          address=(x0 and 0x3F)+(not(x1) and 0x70) << 2                         ' calcola subito l'address
          if address=cvadd then                                                 ' Se e' indirizzato a questo decoder
            reset_out=0                                                         ' Attiva gli output
            service=0                                                           ' Non siamo in service
            mask=1 << (x1 and 0x7)                                              ' seleziona quale e' il bit giusto su cui agire

            if x1.3=1 then                                                      ' si deve settare o resettare?
              ledco=1                                                           ' spegni il LED per 10msec
              select case setmode
                case 0                                                          ' MODO DCC STANDARD========================
                  cmd_set=mask
                case 1                                                          ' MODO MULTIMAUS===========================
                  if (setout and mask)=0 then                                   ' Comando considerato solo se non e' una ripetizione
                    setout=setout or mask                                       ' Il multimaus inizia il treno di impulsi
                    if (uscite and mask)=0 then
                      cmd_set=mask                                              ' Se era OFF attiva l'uscita...
                    else
                      cmd_reset=mask                                            ' Se era ON disattivala
                    end if
                  end if
                case 2                                                          ' MODO IBX=================================
                  if lastcom<>mask then
                    if (uscite and mask)=0 then
                      cmd_set=mask                                              ' Se era OFF attiva l'uscita...
                    else
                      cmd_reset=mask                                            ' Se era ON disattivala
                    end if
                  end if
                  lastcom=mask
                  ctrlco=20                                                     ' 200ms di timeout
              end select
            else
              ledco=5                                                           ' spegni il LED per 50msec
              select case setmode
                case 0                                                          ' MODO DCC STANDARD========================
                  cmd_reset=mask
                case 1                                                          ' MODO MULTIMAUS===========================
                  setout=setout and not(mask)                                   ' Spegni il flag di ripetizione
                case 2                                                          ' MODO IBX=================================
              end select
            end if
          end if

        end if

      case 3                                                                    ' decodifica pacchetti da 4 bytes======================

        if (x0 and 0xF0)=0x70 then                                              ' Questo e' un pacchetto di service mode (direct)
          if service=1 then                                                     ' Se e' il secondo pacchetto di service allora...
            cv_management                                                       ' decodifica il service per leggere/scrivere le CV
          end if
          if reset_out=1 then                                                   ' Service abilitato solo se e' stato ricevuto un reset
            service=1                                                           ' Il primo pacchetto non e' decodificato
            ledco=1                                                            ' spegni il LED per 10msec
          end if
        end if

    end select
  end if

end sub


'===============================================================================
'===============================================================================
' GESTIONE DELLE USCITE
'===============================================================================
'===============================================================================

sub procedure gestisci_uscite

    if cmd_set<>0 then
      if (cmd_set and 0x01)<>0 then                                             ' Se si deve settare l'uscita...
        count1=count_cv3                                                        ' ...copia il suo periodo di attivazione
        uscite.0=1                                                              ' e attivala
      end if
      if (cmd_set and 0x02)<>0 then                                             ' Lo stesso per l'uscita 2
        count2=count_cv3
        uscite.1=1
      end if
      if (cmd_set and 0x04)<>0 then                                             ' Lo stesso per l'uscita 3
        count3=count_cv4
        uscite.2=1
      end if
      if (cmd_set and 0x08)<>0 then                                             ' Lo stesso per l'uscita 4
        count4=count_cv4
        uscite.3=1
      end if
      if (cmd_set and 0x10)<>0 then                                             ' Lo stesso per l'uscita 5
        count5=count_cv5
        uscite.4=1
      end if
      if (cmd_set and 0x20)<>0 then                                             ' Lo stesso per l'uscita 6
        count6=count_cv5
        uscite.5=1
      end if
      if (cmd_set and 0x40)<>0 then                                             ' Lo stesso per l'uscita 7
        count7=count_cv6
        uscite.6=1
      end if
      if (cmd_set and 0x80)<>0 then                                             ' Lo stesso per l'uscita 8
        count8=count_cv6
        uscite.7=1
      end if
      cmd_set=0
    end if


    if count1<>0 then                                                           ' Controllo se i periodi di attivazione delle diverse
      dec(count1)                                                               ' uscite sono finiti. Se il periodo e' finito...
      if (count1=0) then
        cmd_reset.0=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count2<>0 then                                                           ' Lo stesso per l'uscita 2
      dec(count2)
      if (count2=0) then
        cmd_reset.1=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count3<>0 then                                                           ' Lo stesso per l'uscita 3
      dec(count3)
      if (count3=0) then
        cmd_reset.2=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count4<>0 then                                                           ' Lo stesso per l'uscita 4
      dec(count4)
      if (count4=0) then
        cmd_reset.3=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count5<>0 then                                                           ' Lo stesso per l'uscita 5
      dec(count5)
      if (count5=0) then
        cmd_reset.4=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count6<>0 then                                                           ' Lo stesso per l'uscita 6
      dec(count6)
      if (count6=0) then
        cmd_reset.5=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count7<>0 then                                                           ' Lo stesso per l'uscita 7
      dec(count7)
      if (count7=0) then
        cmd_reset.6=1                                                           ' ...allora resetta l'uscita
      end if
    end if
    if count8<>0 then                                                           ' Lo stesso per l'uscita 8
      dec(count8)
      if (count8=0) then
        cmd_reset.7=1                                                           ' ...allora resetta l'uscita
      end if
    end if


    if cmd_reset<>0 then
      if (cmd_reset and 0x01)<>0 then                                           ' Se si deve resettare l'uscita...
        count1=0                                                                ' azzera il suo periodo di attivazione...
        uscite.0=0                                                              ' e spegnila
      end if
      if (cmd_reset and 0x02)<>0 then                                           ' Lo stesso per l'uscita 2
        count2=0
        uscite.1=0
      end if
      if (cmd_reset and 0x04)<>0 then                                           ' Lo stesso per l'uscita 3
        count3=0
        uscite.2=0
      end if
      if (cmd_reset and 0x08)<>0 then                                           ' Lo stesso per l'uscita 4
        count4=0
        uscite.3=0
      end if
      if (cmd_reset and 0x10)<>0 then                                           ' Lo stesso per l'uscita 5
        count5=0
        uscite.4=0
      end if
      if (cmd_reset and 0x20)<>0 then                                           ' Lo stesso per l'uscita 6
        count6=0
        uscite.5=0
      end if
      if (cmd_reset and 0x40)<>0 then                                           ' Lo stesso per l'uscita 7
        count7=0
        uscite.6=0
      end if
      if (cmd_reset and 0x80)<>0 then                                           ' Lo stesso per l'uscita 8
        count8=0
        uscite.7=0
      end if
      cmd_reset=0
    end if

'===============================================================================
'===============================================================================
' MODIFICARE QUESTO BLOCCO PER CAMBIARE I PIN DI USCITA DEL DECODER
'===============================================================================
'===============================================================================

    PORTA.7=uscite.0                                                            ' Copia l'Uscita 1
    PORTA.6=uscite.1                                                            ' Copia l'Uscita 2
    PORTA.0=uscite.2                                                            ' Copia l'Uscita 3
    PORTA.1=uscite.3                                                            ' Copia l'Uscita 4
    PORTB.4=uscite.4                                                            ' Copia l'Uscita 5
    PORTB.5=uscite.5                                                            ' Copia l'Uscita 6
    PORTB.7=uscite.6                                                            ' Copia l'Uscita 7
    PORTB.6=uscite.7                                                            ' Copia l'Uscita 8
   
end sub


'===============================================================================
'===============================================================================
' PROGRAMMA PRINCIPALE
'===============================================================================
'===============================================================================

main:

  TRISA=0x20                                                                    ' tutti i pin della porta A output tranne il 5 (MCLR)
  TRISB=0x01                                                                    ' tutti i pin della porta B output tranne lo 0 (INT)
  PORTA=0x0                                                                     ' Resetta le uscite
  PORTB=0x8

  CMCON=0x7                                                                     ' Comparatori e pin analogici OFF
  PCON.OSCF=1                                                                   ' Frequenza del chip 4MHz
  OPTION_REG=0xC8                                                               ' Pull-up disabilitati, INT triggerato sul fronte in salita, prescaler su TIMER 0
  TMR1H=217                                                                     ' il Timer1 va in overflow ogni 65536-217*256=10000 us
  TMR1L=0
  T1CON=0x01                                                                    ' Timer1 conta con un rate di 1us

  one_count=0                                                                   ' nessun "1" arrivato nel preambolo
  bit_count=0                                                                   ' primo bit del byte
  point=0                                                                       ' primo byte del pacchetto
  state=0                                                                       ' partiamo dallo stato di attesa del preambolo
  ledco=0                                                                       ' LED acceso
  service=0                                                                     ' Non siamo in service
  reset_out=0                                                                   ' Uscite abilitate
  cmd_set=0
  cmd_reset=0
  uscite=0                                                                      ' Tutto spento
  count1=0
  count2=0
  count3=0
  count4=0
  count5=0
  count6=0
  count7=0
  count8=0
  setout=0
  ctrlco=0
  lastcom=0
  INTCON=0x90                                                                   ' interrupt abilitati solo per il pin INT
 
  do loop until EECON1.WR=0                                                     ' Si puo' scrivere/leggere nella EEPROM?
  tmp=eeprom_read(7)                                                            ' Si legge il costruttore
  if tmp<>13 then                                                               ' Se e' diverso da DIY allora bisogna inizializzare
    inizializza_CV                                                              ' Inizializza le CV (solo se alla prima accensione)
  end if
  leggi_CV                                                                      ' Rileggile

  while TRUE                                                                    ' ciclo senza fine per il funzionamento decoder

    if state=3 then                                                             ' se un pacchetto e' completo allora...
      decodifica                                                                ' ...decodificalo
    end if
   
    if PIR1.TMR1IF then                                                         ' base dei tempi per le azioni temporizzate ogni 10msec
      T1CON=0x0                                                                 ' disabilita il timer1
      PIR1.TMR1IF=0                                                             ' resetta il flag di overflow
      TMR1H=217                                                                 ' fai ripartire il conteggio per i 10msec
      TMR1L=0
      T1CON=0x01                                                                ' fai ripartire il Timer1
     
      gestisci_uscite                                                           ' Ogni 10msec -> Gestione delle uscite
     
      if ctrlco<>0 then                                                         ' Gestione del timeout attivazione uscite
        dec(ctrlco)                                                             ' Sono passati altri 10 msec
      else
        lastcom=0                                                               ' alla fine del timeout azzera il flag
      end if

      if ledco<>0 then                                                          ' Gestione del LED ogni 10 msec
        PORTB.3=0                                                               ' Se il contatore e' <>0 allora LED spento
        dec(ledco)                                                              ' Sono passati altri 10 msec
      else
        PORTB.3=1                                                               ' se e' arrivato a 0 riaccendi il LED
      end if

    end if


  wend

end.
ċ
OSD3.zip
(64k)
Davide Fiorini,
02 mag 2010, 08:20