Controllo accessi da remoto

PRINCIPIO DI FUNZIONAMENTO

il Ricevitore è programmato a ricevere una stringa, cifrata secondo l'algoritmo descritto nel post Algoritmi di cifratura proprietari, di 16 byte (128 bit), con la struttura mostrata in Fig.2 del post Protocollo di trasmissione proprietario, ripartita come segue:

  • progressivo d'invio: 4 byte
  • identificativo di serratura: 11 byte
  • comando o identificativo di chiave: 1 byte
Il dispositivo dispone di una memoria non volatile EEPROM di 256 byte che sarà organizzata come segue:

Indirizzo Contenuto
00-03 Progressivo di invio della chiave 00
04-07 Progressivo di invio della chiave 04
08-0B Progressivo di invio della chiave 08
0C-0F Progressivo di invio della chiave 0C
10-13 Progressivo di invio della chiave 10
... ...
E0-E3 Progressivo di invio della chiave E0
E4-E7 Progressivo di invio della chiave E4
E8-EB Progressivo di invio della chiave E8
EC-EF Progressivo di invio della chiave EC
F0-F3 Progressivo di invio della chiave F0
F4-FE Identificativo di serratura
FF byte non usato

permettendo alla serratura la gestione contemporanea fino a un massimo di 61 chiavi (in forma di lettore RFID o telecomando).
Nella modalità di inizializzazione (ponticello del connettore di Reset posizionato fra ON e RST), al ricevimento della stringa cifrata, dopo la decodifica, se il byte di comando è h'FF' il ricevitore memorizza gli 11 byte dell'identificativo di serratura nelle locazioni F4-FE della memoria e viene imposto il progressivo d'invio contenuto nella stringa a tutte le locazioni da 00 a F3 (imponendo h'00000001' di fatto si inizializzano i contatori a inizio conteggio).
Da adesso in poi, nella modalità di funzionamento normale (ponticello del connettore di Reset nella posizione OFF RST), il Ricevitore riconoscerà come valide (dando il consenso al suo relè) tutte le chiavi che invieranno l'identificativo di serratura memorizzato in modo non volatile.
Il progressivo di invio, lungo 4 byte, di ciascuna chiave viene memorizzato nella specifica area EEPROM (per la chiave 00 le locazioni 00-03, per la chiave 04 le locazioni 04-07, ecc.). Se viene ricevuta una stringa di una particolare chiave, con l'identificativo di serratura valido, ma con un progressivo d'invio uguale o inferiore al valore correntemente memorizzato per quella particolare chiave, tale stringa non è considerata valida e non viene dato il consenso. Come già discusso nel post Protocollo di trasmissione proprietario, questo accorgimento previene la possibilità per un intruso di captare il segnale inviato da un utente legittimo, registrarlo e successivamente inviarlo per scopi fraudolenti.
Se durante il funzionamento normale, viene ricevuta una stringa con l'identificativo di serratura corretto e il byte di comando uguale a h'FF', viene reinizializzato il Ricevitore, riportando i progressivi d'invio di tutte le chiavi al valore contenuto nella stringa.

Al modulo RFID è associata la chiave 00 e la modalità di programmazione della serratura. E' sufficiente disporre di due RFID card: ad una si dà la funzione di inviare il codice di programmazione (con il comando h'FF'), all'altra la funzione di utente. E' possible associare, ad altre carte utente, numeri di chiave diversi (h'08', h'0C', h'10', ecc.).

Al telecomando, nel nostro esempio, è associata la chiave h'04'. Tutti i dispositivi realizzano la cifratura/decifratura con le stesse chiavi private (generate dalla stessa password). Nell'esempio se ne adottata una casuale, generata dal simulatore del post Protocollo di trasmissione proprietario. Se si dovesse utilizzare i dispositivi per applicazioni pratiche, si raccomanda di utilizzare il simulatore per generare chiavi private proprie, attraverso una propria password segreta.
Nell'esempio, l'identificativo di serratura è la stringa h'445566778899AABBCCDDEE', che deve essere nota sia al ricevitore, sia ai dispositivi trasmettitori.

PROGRAMMAZIONE E TEST

Di seguito trovate i codici di programmazione del dispositivo lettore RFID di Fig.1, basato sul microcontrollore ATMega328P.

#include <SPI.h>
#include <MFRC522.h>
#include <EEPROM.h> // Libreria di gestione EEPROM
MFRC522 mfrc522(10, 9);
MFRC522::MIFARE_Key key;
/*
 * Initializzazione e Definizione Variabili
*/
#define LED_ON LOW
#define LED_OFF HIGH
constexpr uint8_t Tx_pin = 8;   // Pin di trasmissione
constexpr uint8_t Supply_pin = 7;   // Pin di alimentazione del trasmettirote (attivo HIGH) 
constexpr uint8_t UNO = LOW;     // Segnale di uno logico
constexpr uint8_t ZERO = HIGH;   // Segnale di zero logico     
char prog[8] = "8FA2EA29"; // Inserire qui il proprio codice univoco della RFID Card di Programmazione
char user[8] = "0D957C89"; // Inserire qui il proprio codice univoco della RFID Card Utente
byte usrvl[4], prgvl[4];
/*
**************
 Mappa EEPROM
**************
 00-03 Contatore di chiave
 04 Flag di inizializzazione
 05-FF non usati
*/
constexpr uint8_t Led_Rosso = 4;
constexpr uint8_t Led_Verde = 3;
/*
* PASSWORD GENERATRICE DI ESEMPIO
*
1CA97A224432B78088A91048A5C739C54BAB2C8400372600B8A37C0F825A5386F65F62368CDBF3A69492
DB949DE0D7D069C35640632C7811A6C03C7651A1D070414A8E117B18F5FF9C971568F491AF16D7C75258
4B8130DC5B37C37A540E9EC2945289FA2E424411FDFEA903918119483687A82D7C40A0C8B2D3ACC3DF6E
7A1541885C9090E2FE1652CF87FF35A9CD87456D13944398DD26192672AF8D588D9AD03431173C581C11
4F3BA5B849211A7AC13009833B9AA277EC95A54C943303F20E77972C8F631E0E5565B05D853D7BCD2AF9
69D3C38E10906FCE03BD6A3E4EA2176A9A887582F1CC81901D907C8ACC36CEC8124EE2BB8146C83F2FB2
E0C2E621AF57E4EAE8DE641BA14027631FDB1C4E20C5E9FFC8DA14A73229122122B7D5F519E2DA9D9DC8
CCF394AFC8FFF34ADA97DC4E70958E11DBB1424AAA55B0738ABDC478E46212A00FC7617599265EF717B6
21CCBD2125F780945DDEA454AF2EA2D74A34262770C21A8A862EC61E0022D09D00ADFA815F33BB32866E
6713DB85639E8EBB8B3E129D3FA312F7B90876F495DFC9CC0BB7ED630FCDFD128D67FFA78059D7AAC396
5A0A0C49D25C2C09D136779049E4C14555745CF53352B3C69ECF63898B6A75991CAEC19270ECBF7E1095
D2E1E745F7DFA42B53CE987B6B0881CE0A802C3018EDA109A8FACFCBEA5B9FDC8C18DB0E131E27DF124B
2B2C5E101E5D162D968193F815A2A09B5D692D8C450D81D8
*
*/
    byte Key [][8] = {
    {203, 129, 150, 202, 104, 213, 42, 252},
    {6, 240, 136, 110, 195, 193, 237, 109},
    {218, 208, 198, 117, 74, 137, 219, 76},
    {191, 35, 77, 220, 136, 155, 119, 134},
    {183, 26, 29, 164, 170, 66, 214, 180},
    {223, 11, 22, 186, 122, 42, 126, 133},
    {126, 224, 172, 32, 242, 55, 61, 51},
    {43, 231, 27, 38, 72, 142, 1, 149},
    {52, 6, 93, 0, 117, 239, 26, 26},
    {151, 113, 214, 179, 155, 13, 191, 107},
    {58, 65, 180, 66, 136, 249, 149, 70},
    {176, 20, 66, 20, 58, 248, 67, 150},
    {157, 97, 233, 185, 77, 217, 246, 175},
    {194, 101, 44, 253, 61, 206, 47, 210},
    {199, 20, 201, 193, 206, 164, 24, 48},
    {198, 134, 153, 159, 238, 115, 12, 83},
    {26, 240, 158, 222, 163, 239, 29, 247},
    {201, 83, 138, 247, 42, 56, 116, 21},
    {210, 217, 66, 196, 186, 130, 160, 188},
    {155, 122, 155, 152, 199, 61, 72, 107},
    {7, 220, 21, 14, 155, 109, 135, 75},
    {100, 245, 160, 203, 63, 16, 94, 76},
    {73, 213, 140, 117, 4, 214, 145, 199},
    {131, 65, 111, 158, 17, 6, 7, 32},
    {72, 107, 212, 38, 94, 152, 79, 201},
    {236, 147, 71, 143, 183, 114, 58, 130},
    {101, 196, 214, 23, 35, 6, 85, 129},
    {227, 97, 34, 16, 118, 197, 168, 124},
    {219, 169, 131, 61, 114, 79, 39, 201},
    {85, 150, 166, 90, 233, 238, 254, 26},
    {112, 74, 236, 48, 17, 144, 71, 23},
    {92, 122, 206, 207, 164, 179, 109, 39},
    {183, 80, 89, 133, 74, 245, 39, 227},
    {135, 43, 38, 36, 63, 45, 83, 15},
    {131, 28, 200, 125, 101, 241, 71, 58},
    {51, 89, 255, 81, 106, 83, 79, 131},
    {194, 254, 197, 43, 26, 73, 223, 11},
    {163, 76, 219, 137, 119, 121, 151, 16},
    {96, 125, 131, 86, 83, 180, 152, 251},
    {100, 85, 125, 109, 238, 104, 184, 227},
    {182, 170, 106, 226, 32, 238, 245, 238},
    {83, 32, 127, 45, 85, 121, 170, 157},
    {189, 234, 171, 40, 174, 89, 122, 102},
    {13, 47, 3, 83, 81, 239, 181, 12},
    {197, 79, 183, 173, 25, 219, 88, 50},
    {247, 45, 142, 72, 244, 191, 204, 100},
    {171, 62, 153, 255, 245, 205, 17, 133},
    {41, 155, 189, 246, 48, 223, 236, 42},
    {239, 179, 233, 71, 155, 165, 116, 147},
    {48, 160, 13, 155, 122, 158, 62, 51},
    {140, 177, 253, 6, 41, 40, 151, 159},
    {135, 30, 159, 192, 173, 42, 191, 187},
    {195, 229, 201, 146, 221, 213, 224, 213},
    {236, 204, 248, 34, 53, 218, 65, 3},
    {47, 38, 136, 61, 35, 129, 123, 211},
    {71, 22, 107, 217, 15, 1, 216, 185},
    {186, 185, 241, 184, 158, 69, 115, 206},
    {218, 109, 153, 244, 64, 224, 53, 129},
    {37, 148, 168, 19, 167, 134, 170, 20},
    {41, 172, 153, 72, 176, 134, 164, 152},
    {126, 196, 216, 186, 192, 191, 164, 106},
    {33, 99, 126, 224, 137, 161, 62, 98},
    {4, 176, 112, 177, 169, 247, 203, 103},
    {82, 73, 45, 227, 206, 165, 156, 37},
    {168, 201, 113, 232, 82, 20, 174, 53},
    {208, 181, 253, 161, 239, 174, 203, 112}
    };        
    char s[33];
    byte a[8], b[8], flg[1];
    byte ia[8] = {0, 0, 0, 0, 68,85,102,119};     
    //byte ib[8] = {136, 153, 170, 187, 204, 221,238,255}; // Programming Command
    byte ib[8] = {136, 153, 170, 187, 204, 221, 238, 0}; // User Command
    byte icnt[8] = {0, 0, 0, 1, 0,0,0,0};
void setup() {
    Serial.begin(9600);
    pinMode(Led_Rosso, OUTPUT);   
    pinMode(Led_Verde, OUTPUT);  
    pinMode(Supply_pin, OUTPUT);  
    digitalWrite(Supply_pin, LOW);    // trasmissione disabilitata
    pinMode(Tx_pin, OUTPUT);   
    digitalWrite(Tx_pin, ZERO);    // segnale di trasmissione basso
    for (byte i = 0; i < 6; i++) {
        key.keyByte[i] = 0xff;
    }
    VectorValue(prog, prgvl);
    VectorValue(user, usrvl);   
    digitalWrite(Led_Rosso, LOW);        
    digitalWrite(Led_Verde, LOW);
    delay(1000);    
    digitalWrite(Led_Rosso, HIGH);        
    digitalWrite(Led_Verde, HIGH);     
}
void loop() { 
    SPI.begin();
    delay(500);
    mfrc522.PCD_Init();
    CopyVector(ia, a, 0, 8);
    CopyVector(ib, b, 0, 8);
    delay(300);
    if (mfrc522.PICC_IsNewCardPresent()){
      if (mfrc522.PICC_ReadCardSerial()) {
        if(CompareVector(mfrc522.uid.uidByte, prgvl, 0, 4)) {
          digitalWrite(Led_Verde, LOW);
          digitalWrite(Led_Rosso, LOW);          
          b[7] = 255;                    
          RFTransmit();          
          delay(1000);
          digitalWrite(Led_Verde, HIGH);
          digitalWrite(Led_Rosso, HIGH);
         
        }       
        else if(CompareVector(mfrc522.uid.uidByte, usrvl, 0, 4)) {
          digitalWrite(Led_Verde, LOW);
          RFTransmit();          
          delay(1000);         
          digitalWrite(Led_Verde, HIGH);
        }
        else {
          digitalWrite(Led_Rosso, LOW);
          delay(1000);
          digitalWrite(Led_Rosso, HIGH);
        }                  
      }
    }
    mfrc522.PICC_HaltA();
    mfrc522.PCD_StopCrypto1();    
}
boolean CompareVector(byte *x, byte *z, byte inz, byte dv) {
    byte j;   
    boolean flg = true;
    for (j = inz; j
      if(x[j] != z[j]) flg = false;           
    }
    return flg;
}
void VectorValue(char* code, byte *x) {
    byte j=0;
    for(byte i=0; i<8; i=i+2) {
      x[j] = HextoDec(code[i], code[i+1]);
      j=j+1;
    }
  }
byte HextoDec(char x, char y) {
    byte h, l, r;
    h = 0;
    l = 0;
    if(x>64) h = x - 55;
    else h = x - 48;
    if(y>64) l = y - 55;
    else l = y - 48;
    r = h*16 + l;
    return r;
  }
/*-----( Funzioni di Cifratura )-----*/
void Krypto(byte a[8], byte b[8], byte nit) {
        byte i, j, rck, rtb; 
        byte rs[8];          
        Sum(a, Key[0], a);
        Sum(b, Key[1], b);
        for (i = 1; i
          Xor(a, b, rs);
          rck = b[7] & 1;
          if(rck > 0){
            Swap(rs, rs);  
          }
          rck = b[7] & 63;
          rtb = b[7] & 64;
          if(rtb > 0) LeftRot(rs, rck, rs);        
          else RightRot(rs, rck, rs);
          Sum(rs, Key[2*i], a);  
          Xor(b, a, rs);
          rck = a[7] & 1;
          if(rck > 0){
            Swap(rs, rs);      
          }   
          rck = a[7] & 63;
          rtb = a[7] & 64;
          if(rtb > 0) LeftRot(rs, rck, rs);        
          else RightRot(rs, rck, rs);
          Sum(rs, Key[2*i+1], b);       
        }                  
}
void Sum(byte x[8], byte y[8], byte z[8]) {
    byte rp = 0, i, j;
    int rs;
    for (j = 0; j<8; j++) {
      i = 7 - j;     
      rs = x[i] + y[i] + rp;
      if(rs > 255) { 
        rs = rs - 256;
        rp = 1;
      }
      else rp = 0;
      z[i] = byte(rs);     
    }
}
void LeftRot(byte x[8], byte rotn, byte z[8]) {
    byte rp;
    int rs;
    byte i;
    byte j;
    byte k;
    for (k = 0; k
      rp = 0;
      for (j = 0; j<8; j++) {
        i = 7 - j;     
        rs = x[i] << 1;
        rs = rs | int(rp);
        if(rs > 255) { 
          rs = rs - 256;
          rp = 1;
        }
        else rp = 0;
        z[i] = byte(rs);     
      }
      z[7] = z[7] | rp;
    }    
}
void RightRot(byte x[8], byte rotn, byte z[8]) {
    byte rp;
    byte rs;
    byte j;
    byte k;
    for (k = 0; k
      rp = 0;
      for (j = 0; j<8; j++) {
        rs = rp;
        if((x[j] & 1) > 0) rp = 128;
        else rp = 0;
        z[j] = (x[j] >> 1) | rs;    
      }
      z[0] = z[0] | rp;
    }    
}
void Xor(byte x[8], byte y[8], byte z[8]) {
    byte j;   
    for (j = 0; j<8; j++) {  
      z[j] = x[j]^y[j];
    } 
}
byte UnoNB(byte x[8], byte y[8]) {
    byte u = 0;
    for (byte i = 0; i<8; i++) { 
      for (byte j = 0; j < 8; j++) {
        if(bitRead(x[i], j) == 1) u = u + 1;
        if(bitRead(y[i], j) == 1) u = u + 1; 
      } 
    } 
    return u;        
}
void Swap(byte x[8], byte z[8]) {
    byte j;   
    for (j = 0; j<8; j++) {  
      z[j] = (x[j] << 4) | (x[j] >> 4);
    } 
}
void RFTransmit() {
      byte unocnt;  
      if(b[7]<255){
        EEPROMRead(flg, 1, 4);
        if(flg[0] == 170) { 
          EEPROMRead(a, 4, 0); // Lettura contatore già inizializzato                   
        }
        else { 
// inizializza il contatore a zero   
          EEPROM.write(4, 170);//imposta il flag a h'AA'
        }        
      }      
      Sum(a, icnt, a); // Incremento
      EEPROMWrite(a, 4, 0);      
      VectorPrint(a, 8);             
      VectorPrint(b, 8);
      Serial.println();                            
      Krypto(a, b, 33);    
      unocnt = UnoNB(a, b);
      digitalWrite(Supply_pin, HIGH);    // Abilitazione trasmissione
      for (byte k = 0; k < 10; k++) {
        digitalWrite(Tx_pin, UNO);    // Start bit     
        delayMicroseconds(1200);        
        for (byte i = 0; i < 8; i++) {
          ByteTx(a[i]);     
        }
        for (byte i = 0; i < 8; i++) {
          ByteTx(b[i]);
        } 
        ByteTx(unocnt);  // Invio di un byte di controllo (numero di uno)    
      }
      digitalWrite(Supply_pin, LOW);    // Disabilitazione trasmissione   
}    
void ByteTx(byte xc){
    for (byte i = 0; i < 8; i++) {
      digitalWrite(Tx_pin, ZERO);    // ith bit
      if(bitRead(xc, 7-i) == 1){
        delayMicroseconds(600); // bit a 1         
      }
      else {
        delayMicroseconds(300); // bit a 0          
      }     
      digitalWrite(Tx_pin, UNO);    // end bit
      delayMicroseconds(300); // durata end bit   
    }   
}
void CopyVector(byte *src, byte *dst, byte inz, byte dv) {
    for (byte j = inz; j
      dst[j] = src[j];          
    }
}
void DectoHex(byte z, char ch[2]) {
    byte nb;
    nb = z / 16;
    if (nb>9){nb = nb + 55;}
    else {nb = nb + 48;}
    ch[0] = char(nb);
    nb = z % 16;
    if (nb>9){nb = nb + 55;}
    else {nb = nb + 48;}
    ch[1] = char(nb);
}
void VectorPrint(byte *x, byte dv) {      
    char ch[2];
    for (byte i = 0; i < dv; i++) {
      DectoHex(x[i], ch);
      Serial.print(ch[0]);
      Serial.print(ch[1]);         
    }    
}
/* Gestione Contatore su EEPROM 00-03 */
void EEPROMRead(byte *x, int dv, int adr){
  for ( int i = 0; i < dv; i++) {      // Legge il vettore dalla EEPROM
    x[i] = EEPROM.read(adr+i);    // Salva il byte nel vettore
  }
}
void EEPROMWrite(byte *x, int dv, int adr){
  for ( int i = 0; i < dv; i++) {      // Scrive il vettore nella EEPROM
     EEPROM.write(adr+i, x[i]);
  }
}

Qui di seguito trovate i codici di programmazione del dispositivo Ricevitore di Fig.5, basato sul microcontrollore PIC16F684.

;**********************************************************************
;    Algoritmo RC5-64-32-528									      *
;**********************************************************************
;                                                                     *
;    Filename:	    P16F684_Lock64.asm                                *
;    Date:                                                            *
;    File Version: Versione 1.0                                      *
;                                                                     *
;    Author:  InTeAS WebMaster                                        *
;    Company: https://www.inteas.it                                   *
;                                                                     * 
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files Required: P16F684.INC                                      *
;                                                                     *
;**********************************************************************
;                                                                     
	list		p=16f684		; list directive to define processor
	#include	<P16F684.inc>		; processor specific variable definitions	
	__CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF
;
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file. 
; See respective data sheet for additional information on configuration word.
;
;**************
; Mappa EEPROM
;**************
;
; 61 chiavi programmabili
; 00-03 Contatore della chiave 00
; 04-07 Contatore della chiave 04
; 08-0B Contatore della chiave 08
; 0C-0F Contatore della chiave 0C
; .....
; E0-E3 Contatore della chiave E0
; E4-E7 Contatore della chiave E4
; E8-EB Contatore della chiave E8
; EC-EF Contatore della chiave EC
; F0-F3 Contatore della chaive F0
;
; F4-FE Identificativo di serratura
; FF non usato
;
;******************************
; DEFINIZIONE VARIABILI LOCALI
;******************************
;
; Interval 0x20 - 0x7F , Bank 0
; Interval 0xA0 - 0xBF , Bank 1
;
;**********************
; Bank0
;**********************
;
; 20-27 S_2i 
; 28-2F S_2i+1
; 30-37 A, KrA
; 38-3F B, KrB
;
CMDRCV        EQU  0x3F
UNORCV        EQU  0x40 
WTCNT1		  EQU  0x7F
WTCNT2        EQU  0x7E
;
;**********************
; Bank1
;**********************
;
COUNT1        EQU  0xBF
COUNT2        EQU  0xBE
SEQCNT        EQU  0xBD
BYTCNT		  EQU  0xBC
TBLNMB        EQU  0xBB
TBLADR        EQU  0xBA
BYTEVL		  EQU  0xB9
ITERAZ        EQU  0xB8
OLDCARRY	  EQU  0xB7
NEWCARRY      EQU  0xB6
COMPLRF		  EQU  0xB5
MASK 		  EQU  0xB4
ADDR2         EQU  0xB3
ADDR1         EQU  0xB2
ADDR0         EQU  0xB1
NBYTES        EQU  0xB0
UNONB         EQU  0xAF
ERRFLG        EQU  0xAE
CONFR         EQU  0xAD
;
;**********************************************************************
	ORG		0x000			; processor reset vector
	goto	Init			; go to beginning of program
;
	ORG		0x004			; interrupt vector location
	goto Init
;
Init:
;
; OPTION Register, on reset all bits = 1
	; bit 7 (NOT_RAPU) Weak Pull-Ups Disabled	
	; bit 6 (INTEDG) Interrupt Edge Select
	; bit 5 (T0CS) Timer0 Source Selection: 1= T0CKI Transition (default), 0= Internal Instruction (CLKOUT) 
	; bit 4 (T0SE) Timer0 Source Edge Selection: 1 = H-to-L (default), 0= L-to-H  
	; bit 3 (PSA) Prescaler Assignment: 1= to WDT (default), 0= to Timer0	
	; bits 2:0 (PS2,PS1,PS0) Prescaler Rate Selection: 1:128 default
;
;	movlw b'11010111' ; T0CS= 0 : Internal Timer0 (RC5 can be I/O line)
;
	bsf STATUS,RP0 ; Bank 1		
	movwf OPTION_REG
;
; I/O Summary
;
; PORTA,5 INPUT  (pin  2) : NC
; PORTA,4 INPUT  (pin  3) : NC 
; PORTA,3 INPUT  (pin  4) : NC
; PORTA,2 INPUT  (pin 11) : NC
; PORTA,1 INPUT  (pin 12) : NC
; PORTA,0 INPUT  (pin 13) : Soft Reset (attivo su 0)
;
; PORTC,5 INPUT  (pin  5) : NC
; PORTC,4 OUTPUT (pin  6) : Consenso (attivo su 1)
; PORTC,3 OUTPUT (pin  7) : Abilitazione Ricevitore (attivo su 0)
; PORTC,2 INPUT  (pin  8) : Lettura ricevitore
; PORTC,1 OUTPUT (pin  9) : Probe Led (attivo su 1)
; PORTC,0 INPUT  (pin 10) : NC
;
; *******************************
; Set of the PORTA I/O (bit 5:0)
; *******************************
;
	bcf STATUS,RP0 ; Bank 0
	movlw h'07' ; Set RA<2:0> to digital I/O
	movwf CMCON0
	bsf STATUS,RP0 ; Bank 1
	clrf ANSEL ; Digital I/O only: no analogical function
; 1=input 0=output	
	movlw b'11111111'
	movwf TRISA	; write in TRISA register	
; 
; *******************************
; Set of the PORTC I/O (bit 5:0)
; *******************************
;
	movlw b'11100101'
	movwf TRISC ; write in TRISC register	
	bcf STATUS,RP0 ; Bank 0
	bsf PORTC,3    ; Disabilita il Ricevitore
	bcf PORTC,4    ; Disabilita il Consenso 
	bcf PORTC,1    ; Spegne il Probe Led
	bsf STATUS,RP0 ; Bank 1 condizione normale di funzionamento
;
Main:
	bcf STATUS,RP0 ; Bank 0
	bcf PORTC,3    ; Abilita il ricevitore
	bsf STATUS,RP0 ; Bank 1
;
	call LDELAY_STD     ;Attende che si stabilizzi
;
; Loop di osservazione ricevitore
;
	movlw h'30'
	movwf FSR
	movlw h'08'
	movwf BYTCNT ; contatore di bit di byte
;
; Comincia la memorizzazione
;
	bcf STATUS,RP0 ; Bank 0
	btfsc PORTC,2 ; salta  se ho trovato uno zero 
	goto InitUno ; ho trovato un uno al primo colpo
;
InitZero:
	bsf STATUS,RP0 ; Bank 1		
	clrf COUNT1; azzero contatore di zeri iniziale
;
InitZeroSeq:
	bcf STATUS,RP0 ; Bank 0
	btfsc PORTC,2 ; salta  se=0
	goto InitUno ; è arrivato un uno
	bsf STATUS,RP0 ; Bank 1
	incf COUNT1
	btfss STATUS,Z ; salta se Z=1: è il 256simo zero consecutivo
    goto InitZeroSeq
; è il 256simo zero consecutivo: non c'è trasmissione in corso 
	goto Exit ; sequenza abortita
;
; Ricerca dello start bit
;
InitUno:
	bsf STATUS,RP0 ; Bank 1
	clrf COUNT2 ;  azzero contatore di uno
;
InitUnoSeq:
	bcf STATUS,RP0 ; Bank 0
	btfss PORTC,2 ; salta  se=1
	goto InitZero ; è arrivato uno zero: non è lo start bit, ricomincio
	bsf STATUS,RP0 ; Bank 1
	incf COUNT2
	btfss COUNT2,7 ; salta se max uno consecutivi
    goto InitUnoSeq
;
; è il max uno consecutivi: agganciata trasmissione in corso
; 
	clrf UNONB ; azzero il Contatore di Bit ad uno
;
; Memorizzazione Trasmissione
;
UnoLoop:
	bsf STATUS,RP0 ; Bank 1
	clrf COUNT2 ;  azzero contatore di uno: serve per trovare il fine trasmissione
;
UnoSeq:
	bcf STATUS,RP0 ; Bank 0
	btfss PORTC,2 ; salta  se=1
	goto ZeroLoop ; è arrivato uno zero
	bsf STATUS,RP0 ; Bank 1
	incf COUNT2
	btfss COUNT2,7 ; salta se max uno consecutivi ; fine trasmissione
    goto UnoSeq
;
; è il max uno consecutivi: fine trasmissione
;
	goto FineLoop
;
ZeroLoop:
	bsf STATUS,RP0 ; Bank 1
;
InZeroSeq:
	clrf COUNT1 ; azzero contatore di zeri
;
ZeroSeq:
	bcf STATUS,RP0 ; Bank 0
	btfsc PORTC,2 ; salta  se=0
	goto CalcoloBit ; è arrivato un uno, calcola il bit
	bsf STATUS,RP0 ; Bank 1
	incf COUNT1
	btfss STATUS,Z ; salta se Z=1: è il 256simo zero consecutivo
    goto ZeroSeq
;
; è il 256simo zero consecutivo: sequenza abortita
;
	bsf STATUS,RP0 ; Bank 1	 
	goto Exit
;
CalcoloBit:
	bsf STATUS,RP0 ; Bank 1
;
; INT = 3D; INT unità di misura dell'intervallo di bit 
; 1xINT => Bit=0; 2xINT => Bit=1
;
	movlw h'3D'
	subwf COUNT1,w ; se COUNT1 > B7 C=1, se COUNT1 <= B7 C=0
;
; Il conteggio dei Bit a Uno non si applica al 17simo byte di controllo
; (che è nella posizione UNORCV, 0x40)
;
	btfsc FSR,6 ; se FSR nel range 30-3F esegue il conteggio Bit a Uno
	goto FineUnoCount ; se FSR = 40 salta il conteggio	
;
; Conteggio Bit a UNO
;
	btfsc STATUS,0 ; salta se C=0 (conta gli Uno)
	incf UNONB ; se C=1 incrementa il Contatore di Bit a Uno 
;
FineUnoCount:
	rlf INDF,1 ; salvo il bit nel byte corrente
	decfsz BYTCNT,1
	goto UnoLoop ; vai al conteggio degli uno
;
; Completato un byte
;
	incf FSR ; incremento il contatore di byte
	movlw h'08'
	movwf BYTCNT ; ricarico il contatore di bit di byte
	goto UnoLoop ; vai al conteggio degli uno
;
FineLoop:
	bcf STATUS,RP0 ; Bank 0
	bsf PORTC,2    ; Disabilita il ricevitore
	movf UNORCV,w ; mette in w il numero di uno ricevuto
	bsf STATUS,RP0 ; Bank 1
;
; Misura la qualità della trasmissione
;
	subwf UNONB,w ; confronta UNONB con UNORCV
	btfss STATUS,Z ; se Z=1 salta e continua 
	goto Exit ; UNONB <> UNORCV; Z=0 codice non validato
;
	movlw h'08'
	movwf NBYTES ; numero bytes	
	call DECIFRATURA8	
;
	bcf STATUS,RP0 ; Bank 0
	btfsc PORTA,0 ; salta  se ho trovato uno zero -> RESET
	goto NoReset
;
; SEQUENZA DI RESET
; 
; Verifica che sia un comando di programmazione (byte in 3F  = h'FF') 	
;
	movlw h'01'
	addwf CMDRCV,w
	btfss STATUS,Z ; se Z=1 salta e continua 
	goto Exit ; non e' un comando di programmazione: comando non valido	
;
; E' un comando di programmazione con Reset in corso: 
; quindi cambio Codice Serratura e azzero tutti i contatori
;
	bsf STATUS,RP0 ; Bank 1
	call LOCKID_SAVE
	call COUNTERS_RESET
	goto Exit
;
NoReset:
	bsf STATUS,RP0 ; Bank 1
	call LOCKID_RECOV	
	movlw h'0B'
	movwf SEQCNT
	movlw h'34'
	call SEQVALID	
	movf CONFR,w 
	btfsc STATUS,Z ; se Z=0 salta e continua 
	goto Exit ; CONFR = 0 Z=1 codice non validato
;
; Verifica che sia un comando di programmazione (byte in 3F  = h'FF') 	
;
	movlw h'01'
	bcf STATUS,RP0 ; Bank 0
	addwf CMDRCV,w
	bsf STATUS,RP0 ; Bank 1
	btfss STATUS,Z ; se Z=1 salta e continua 
	goto UserCard ;e' una chiave utente
;
; Comando di programmazione senza Reset: azzera tutti i contatori
; e da' il consenso		
;
	call COUNTERS_RESET	
	goto Consenso
;
UserCard:
;
; Controlla l'avanzamento del contatore	
;
; recupera il contatore memorizzato della chiave corrente puntata in 3F
	call COUNTER_RECOV 
; copia il contatore della chiave corrente in 50-53 per il confronto 
	call COUNTER_COPY
;
	movlw h'04'
	movwf NBYTES ; numero bytes
;
	movlw h'43'
	call SOTTR
	movf NEWCARRY,w 
	btfsc STATUS,Z ; se Z=0 salta e continua 
	goto Exit ; NEWCARRY = 0 Z=1 contatore corrente minore 
			  ; di quello memorizzato: non valido
;
; Contatore corrente = contatore memorizzato: non valido 
;
	movlw h'04'
	movwf SEQCNT
	movlw h'50'
	call ZEROTEST	
	movf CONFR,w 
	btfss STATUS,Z ; se Z=1 salta e continua 
	goto Exit ; CONFR = 1 Z=0  contatore gia' usato
;
Consenso:
;
; Consenso ricevuto
;
	bcf STATUS,RP0 ; Bank 0
	bsf PORTC,4 ; Attiva il Consenso
	bsf PORTC,1 ; Accende il Probe Led
	bsf STATUS,RP0 ; Bank 1
	movlw h'04'
	call LDELAY
;
	bcf STATUS,RP0 ; Bank 0
	bcf PORTC,4 ; Disattiva il Consenso
	bcf PORTC,1 ; Spegne il Probe Led	
	bsf STATUS,RP0 ; Bank 1
;
FineAzione:
;
; Salva il contatore della chiave corrente nella EEPROM
;
	call COUNTER_SAVE
;
Exit:
	bcf STATUS,RP0 ; Bank 0
	bsf PORTC,3    ; Disabilita il ricevitore
	bsf STATUS,RP0 ; Bank 1
;
; Ritorno all'inizio
;
	goto Main 
;
;*********************************************
; PASSWORD GENERATRICE DI ESEMPIO
;*********************************************
;
; 1CA97A224432B78088A91048A5C739C54BAB2C8400372600B8A37C0F825A5386F65F62368CDBF3A694
; 92DB949DE0D7D069C35640632C7811A6C03C7651A1D070414A8E117B18F5FF9C971568F491AF16D7C7
; 52584B8130DC5B37C37A540E9EC2945289FA2E424411FDFEA903918119483687A82D7C40A0C8B2D3AC
; C3DF6E7A1541885C9090E2FE1652CF87FF35A9CD87456D13944398DD26192672AF8D588D9AD0343117
; 3C581C114F3BA5B849211A7AC13009833B9AA277EC95A54C943303F20E77972C8F631E0E5565B05D85
; 3D7BCD2AF969D3C38E10906FCE03BD6A3E4EA2176A9A887582F1CC81901D907C8ACC36CEC8124EE2BB
; 8146C83F2FB2E0C2E621AF57E4EAE8DE641BA14027631FDB1C4E20C5E9FFC8DA14A73229122122B7D5
; F519E2DA9D9DC8CCF394AFC8FFF34ADA97DC4E70958E11DBB1424AAA55B0738ABDC478E46212A00FC7
; 617599265EF717B621CCBD2125F780945DDEA454AF2EA2D74A34262770C21A8A862EC61E0022D09D00
; ADFA815F33BB32866E6713DB85639E8EBB8B3E129D3FA312F7B90876F495DFC9CC0BB7ED630FCDFD12
; 8D67FFA78059D7AAC3965A0A0C49D25C2C09D136779049E4C14555745CF53352B3C69ECF63898B6A75
; 991CAEC19270ECBF7E1095D2E1E745F7DFA42B53CE987B6B0881CE0A802C3018EDA109A8FACFCBEA5B
; 9FDC8C18DB0E131E27DF124B2B2C5E101E5D162D968193F815A2A09B5D692D8C450D81D8
;
;*********************************************
;
;************************
;TABLE 1
;************************
	ORG		0x0FF
TABLE1:
	addwf PCL
;s[2] = 'DAD0C6754A89DB4C'
	retlw h'DA'
	retlw h'D0'
	retlw h'C6'
	retlw h'75'
	retlw h'4A'
	retlw h'89'
	retlw h'DB'
	retlw h'4C'
;s[3] = 'BF234DDC889B7786'
	retlw h'BF'
	retlw h'23'
	retlw h'4D'
	retlw h'DC'
	retlw h'88'
	retlw h'9B'
	retlw h'77'
	retlw h'86'
;s[4] = 'B71A1DA4AA42D6B4'
	retlw h'B7'
	retlw h'1A'
	retlw h'1D'
	retlw h'A4'
	retlw h'AA'
	retlw h'42'
	retlw h'D6'
	retlw h'B4'
;s[5] = 'DF0B16BA7A2A7E85'
	retlw h'DF'
	retlw h'0B'
	retlw h'16'
	retlw h'BA'
	retlw h'7A'
	retlw h'2A'
	retlw h'7E'
	retlw h'85'
;s[6] = '7EE0AC20F2373D33'
	retlw h'7E'
	retlw h'E0'
	retlw h'AC'
	retlw h'20'
	retlw h'F2'
	retlw h'37'
	retlw h'3D'
	retlw h'33'
;s[7] = '2BE71B26488E0195'
	retlw h'2B'
	retlw h'E7'
	retlw h'1B'
	retlw h'26'
	retlw h'48'
	retlw h'8E'
	retlw h'01'
	retlw h'95'
;s[8] = '34065D0075EF1A1A'
	retlw h'34'
	retlw h'06'
	retlw h'5D'
	retlw h'00'
	retlw h'75'
	retlw h'EF'
	retlw h'1A'
	retlw h'1A'
;s[9] = '9771D6B39B0DBF6B'
	retlw h'97'
	retlw h'71'
	retlw h'D6'
	retlw h'B3'
	retlw h'9B'
	retlw h'0D'
	retlw h'BF'
	retlw h'6B'
;s[10] = '3A41B44288F99546'
	retlw h'3A'
	retlw h'41'
	retlw h'B4'
	retlw h'42'
	retlw h'88'
	retlw h'F9'
	retlw h'95'
	retlw h'46'
;s[11] = 'B01442143AF84396'
	retlw h'B0'
	retlw h'14'
	retlw h'42'
	retlw h'14'
	retlw h'3A'
	retlw h'F8'
	retlw h'43'
	retlw h'96'
;s[12] = '9D61E9B94DD9F6AF'
	retlw h'9D'
	retlw h'61'
	retlw h'E9'
	retlw h'B9'
	retlw h'4D'
	retlw h'D9'
	retlw h'F6'
	retlw h'AF'
;s[13] = 'C2652CFD3DCE2FD2'
	retlw h'C2'
	retlw h'65'
	retlw h'2C'
	retlw h'FD'
	retlw h'3D'
	retlw h'CE'
	retlw h'2F'
	retlw h'D2'
;s[14] = 'C714C9C1CEA41830'
	retlw h'C7'
	retlw h'14'
	retlw h'C9'
	retlw h'C1'
	retlw h'CE'
	retlw h'A4'
	retlw h'18'
	retlw h'30'
;s[15] = 'C686999FEE730C53'
	retlw h'C6'
	retlw h'86'
	retlw h'99'
	retlw h'9F'
	retlw h'EE'
	retlw h'73'
	retlw h'0C'
	retlw h'53'
;s[16] = '1AF09EDEA3EF1DF7'
	retlw h'1A'
	retlw h'F0'
	retlw h'9E'
	retlw h'DE'
	retlw h'A3'
	retlw h'EF'
	retlw h'1D'
	retlw h'F7'
;s[17] = 'C9538AF72A387415'
	retlw h'C9'
	retlw h'53'
	retlw h'8A'
	retlw h'F7'
	retlw h'2A'
	retlw h'38'
	retlw h'74'
	retlw h'15'
;s[18] = 'D2D942C4BA82A0BC'
	retlw h'D2'
	retlw h'D9'
	retlw h'42'
	retlw h'C4'
	retlw h'BA'
	retlw h'82'
	retlw h'A0'
	retlw h'BC'
;s[19] = '9B7A9B98C73D486B'
	retlw h'9B'
	retlw h'7A'
	retlw h'9B'
	retlw h'98'
	retlw h'C7'
	retlw h'3D'
	retlw h'48'
	retlw h'6B'
;s[20] = '07DC150E9B6D874B'
	retlw h'07'
	retlw h'DC'
	retlw h'15'
	retlw h'0E'
	retlw h'9B'
	retlw h'6D'
	retlw h'87'
	retlw h'4B'
;s[21] = '64F5A0CB3F105E4C'
	retlw h'64'
	retlw h'F5'
	retlw h'A0'
	retlw h'CB'
	retlw h'3F'
	retlw h'10'
	retlw h'5E'
	retlw h'4C'
;s[22] = '49D58C7504D691C7'
	retlw h'49'
	retlw h'D5'
	retlw h'8C'
	retlw h'75'
	retlw h'04'
	retlw h'D6'
	retlw h'91'
	retlw h'C7'
;s[23] = '83416F9E11060720'
	retlw h'83'
	retlw h'41'
	retlw h'6F'
	retlw h'9E'
	retlw h'11'
	retlw h'06'
	retlw h'07'
	retlw h'20'
;s[24] = '486BD4265E984FC9'
	retlw h'48'
	retlw h'6B'
	retlw h'D4'
	retlw h'26'
	retlw h'5E'
	retlw h'98'
	retlw h'4F'
	retlw h'C9'
;s[25] = 'EC93478FB7723A82'
	retlw h'EC'
	retlw h'93'
	retlw h'47'
	retlw h'8F'
	retlw h'B7'
	retlw h'72'
	retlw h'3A'
	retlw h'82'
;s[26] = '65C4D61723065581'
	retlw h'65'
	retlw h'C4'
	retlw h'D6'
	retlw h'17'
	retlw h'23'
	retlw h'06'
	retlw h'55'
	retlw h'81'
;s[27] = 'E361221076C5A87C'
	retlw h'E3'
	retlw h'61'
	retlw h'22'
	retlw h'10'
	retlw h'76'
	retlw h'C5'
	retlw h'A8'
	retlw h'7C'
;s[28] = 'DBA9833D724F27C9'
	retlw h'DB'
	retlw h'A9'
	retlw h'83'
	retlw h'3D'
	retlw h'72'
	retlw h'4F'
	retlw h'27'
	retlw h'C9'
;s[29] = '5596A65AE9EEFE1A'
	retlw h'55'
	retlw h'96'
	retlw h'A6'
	retlw h'5A'
	retlw h'E9'
	retlw h'EE'
	retlw h'FE'
	retlw h'1A'
;s[30] = '704AEC3011904717'
	retlw h'70'
	retlw h'4A'
	retlw h'EC'
	retlw h'30'
	retlw h'11'
	retlw h'90'
	retlw h'47'
	retlw h'17'
;s[31] = '5C7ACECFA4B36D27'
	retlw h'5C'
	retlw h'7A'
	retlw h'CE'
	retlw h'CF'
	retlw h'A4'
	retlw h'B3'
	retlw h'6D'
	retlw h'27'
;s[32] = 'B75059854AF527E3'
	retlw h'B7'
	retlw h'50'
	retlw h'59'
	retlw h'85'
	retlw h'4A'
	retlw h'F5'
	retlw h'27'
	retlw h'E3'
;s[33] = '872B26243F2D530F'
	retlw h'87'
	retlw h'2B'
	retlw h'26'
	retlw h'24'
	retlw h'3F'
	retlw h'2D'
	retlw h'53'
	retlw h'0F'
;
;************************************************************
; ROUTINES COMUNI 
;************************************************************
	ORG		0x200
	nop
	nop
;
;************************
;TABLE 2
;************************
;
	ORG		0x2FF
TABLE2:
	addwf PCL;s[34] = '831CC87D65F1473A'
	retlw h'83'
	retlw h'1C'
	retlw h'C8'
	retlw h'7D'
	retlw h'65'
	retlw h'F1'
	retlw h'47'
	retlw h'3A'
;s[35] = '3359FF516A534F83'
	retlw h'33'
	retlw h'59'
	retlw h'FF'
	retlw h'51'
	retlw h'6A'
	retlw h'53'
	retlw h'4F'
	retlw h'83'
;s[36] = 'C2FEC52B1A49DF0B'
	retlw h'C2'
	retlw h'FE'
	retlw h'C5'
	retlw h'2B'
	retlw h'1A'
	retlw h'49'
	retlw h'DF'
	retlw h'0B'
;s[37] = 'A34CDB8977799710'
	retlw h'A3'
	retlw h'4C'
	retlw h'DB'
	retlw h'89'
	retlw h'77'
	retlw h'79'
	retlw h'97'
	retlw h'10'
;s[38] = '607D835653B498FB'
	retlw h'60'
	retlw h'7D'
	retlw h'83'
	retlw h'56'
	retlw h'53'
	retlw h'B4'
	retlw h'98'
	retlw h'FB'
;s[39] = '64557D6DEE68B8E3'
	retlw h'64'
	retlw h'55'
	retlw h'7D'
	retlw h'6D'
	retlw h'EE'
	retlw h'68'
	retlw h'B8'
	retlw h'E3'
;s[40] = 'B6AA6AE220EEF5EE'
	retlw h'B6'
	retlw h'AA'
	retlw h'6A'
	retlw h'E2'
	retlw h'20'
	retlw h'EE'
	retlw h'F5'
	retlw h'EE'
;s[41] = '53207F2D5579AA9D'
	retlw h'53'
	retlw h'20'
	retlw h'7F'
	retlw h'2D'
	retlw h'55'
	retlw h'79'
	retlw h'AA'
	retlw h'9D'
;s[42] = 'BDEAAB28AE597A66'
	retlw h'BD'
	retlw h'EA'
	retlw h'AB'
	retlw h'28'
	retlw h'AE'
	retlw h'59'
	retlw h'7A'
	retlw h'66'
;s[43] = '0D2F035351EFB50C'
	retlw h'0D'
	retlw h'2F'
	retlw h'03'
	retlw h'53'
	retlw h'51'
	retlw h'EF'
	retlw h'B5'
	retlw h'0C'
;s[44] = 'C54FB7AD19DB5832'
	retlw h'C5'
	retlw h'4F'
	retlw h'B7'
	retlw h'AD'
	retlw h'19'
	retlw h'DB'
	retlw h'58'
	retlw h'32'
;s[45] = 'F72D8E48F4BFCC64'
	retlw h'F7'
	retlw h'2D'
	retlw h'8E'
	retlw h'48'
	retlw h'F4'
	retlw h'BF'
	retlw h'CC'
	retlw h'64'
;s[46] = 'AB3E99FFF5CD1185'
	retlw h'AB'
	retlw h'3E'
	retlw h'99'
	retlw h'FF'
	retlw h'F5'
	retlw h'CD'
	retlw h'11'
	retlw h'85'
;s[47] = '299BBDF630DFEC2A'
	retlw h'29'
	retlw h'9B'
	retlw h'BD'
	retlw h'F6'
	retlw h'30'
	retlw h'DF'
	retlw h'EC'
	retlw h'2A'
;s[48] = 'EFB3E9479BA57493'
	retlw h'EF'
	retlw h'B3'
	retlw h'E9'
	retlw h'47'
	retlw h'9B'
	retlw h'A5'
	retlw h'74'
	retlw h'93'
;s[49] = '30A00D9B7A9E3E33'
	retlw h'30'
	retlw h'A0'
	retlw h'0D'
	retlw h'9B'
	retlw h'7A'
	retlw h'9E'
	retlw h'3E'
	retlw h'33'
;s[50] = '8CB1FD062928979F'
	retlw h'8C'
	retlw h'B1'
	retlw h'FD'
	retlw h'06'
	retlw h'29'
	retlw h'28'
	retlw h'97'
	retlw h'9F'
;s[51] = '871E9FC0AD2ABFBB'
	retlw h'87'
	retlw h'1E'
	retlw h'9F'
	retlw h'C0'
	retlw h'AD'
	retlw h'2A'
	retlw h'BF'
	retlw h'BB'
;s[52] = 'C3E5C992DDD5E0D5'
	retlw h'C3'
	retlw h'E5'
	retlw h'C9'
	retlw h'92'
	retlw h'DD'
	retlw h'D5'
	retlw h'E0'
	retlw h'D5'
;s[53] = 'ECCCF82235DA4103'
	retlw h'EC'
	retlw h'CC'
	retlw h'F8'
	retlw h'22'
	retlw h'35'
	retlw h'DA'
	retlw h'41'
	retlw h'03'
;s[54] = '2F26883D23817BD3'
	retlw h'2F'
	retlw h'26'
	retlw h'88'
	retlw h'3D'
	retlw h'23'
	retlw h'81'
	retlw h'7B'
	retlw h'D3'
;s[55] = '47166BD90F01D8B9'
	retlw h'47'
	retlw h'16'
	retlw h'6B'
	retlw h'D9'
	retlw h'0F'
	retlw h'01'
	retlw h'D8'
	retlw h'B9'
;s[56] = 'BAB9F1B89E4573CE'
	retlw h'BA'
	retlw h'B9'
	retlw h'F1'
	retlw h'B8'
	retlw h'9E'
	retlw h'45'
	retlw h'73'
	retlw h'CE'
;s[57] = 'DA6D99F440E03581'
	retlw h'DA'
	retlw h'6D'
	retlw h'99'
	retlw h'F4'
	retlw h'40'
	retlw h'E0'
	retlw h'35'
	retlw h'81'
;s[58] = '2594A813A786AA14'
	retlw h'25'
	retlw h'94'
	retlw h'A8'
	retlw h'13'
	retlw h'A7'
	retlw h'86'
	retlw h'AA'
	retlw h'14'
;s[59] = '29AC9948B086A498'
	retlw h'29'
	retlw h'AC'
	retlw h'99'
	retlw h'48'
	retlw h'B0'
	retlw h'86'
	retlw h'A4'
	retlw h'98'
;s[60] = '7EC4D8BAC0BFA46A'
	retlw h'7E'
	retlw h'C4'
	retlw h'D8'
	retlw h'BA'
	retlw h'C0'
	retlw h'BF'
	retlw h'A4'
	retlw h'6A'
;s[61] = '21637EE089A13E62'
	retlw h'21'
	retlw h'63'
	retlw h'7E'
	retlw h'E0'
	retlw h'89'
	retlw h'A1'
	retlw h'3E'
	retlw h'62'
;s[62] = '04B070B1A9F7CB67'
	retlw h'04'
	retlw h'B0'
	retlw h'70'
	retlw h'B1'
	retlw h'A9'
	retlw h'F7'
	retlw h'CB'
	retlw h'67'
;s[63] = '52492DE3CEA59C25'
	retlw h'52'
	retlw h'49'
	retlw h'2D'
	retlw h'E3'
	retlw h'CE'
	retlw h'A5'
	retlw h'9C'
	retlw h'25'
;s[64] = 'A8C971E85214AE35'
	retlw h'A8'
	retlw h'C9'
	retlw h'71'
	retlw h'E8'
	retlw h'52'
	retlw h'14'
	retlw h'AE'
	retlw h'35'
;s[65] = 'D0B5FDA1EFAECB70'
	retlw h'D0'
	retlw h'B5'
	retlw h'FD'
	retlw h'A1'
	retlw h'EF'
	retlw h'AE'
	retlw h'CB'
	retlw h'70'
;
;************************
;FINE TABLE
;************************ 
;
;************************************************************
; ROUTINES COMUNI E DI DECIFRATURA (400-7FF)
;************************************************************
	ORG		0x400
;************************************************************
; DECIFRATURA a 8 bytes
;************************************************************
;
DECIFRATURA8:
	movlw h'03'
	movwf TBLNMB
	movlw h'FF'
	movwf TBLADR
	movlw h'20'
	movwf ITERAZ
LoopDecifr8:
	call DSECRETKEYS8
; Recupero di B
	movlw h'2F'
	call SOTTR ; b = (b - s2i+1)
	bcf STATUS,RP0 ; Bank 0	
	movf 0x37,w
	bsf STATUS,RP0 ; Bank 1
	movwf SEQCNT
	btfsc SEQCNT,6	
	goto RgtRotazBD8
; Rotazioni a sinistra
	movlw h'3F'
	call LEFT_ROT 
	goto ContBD8
; Rotazioni a destra
RgtRotazBD8:
	movlw h'38'
	call RIGHT_ROT
ContBD8:
	btfss SEQCNT,0
	goto NoSwapBD8
; Swap di B
	movlw h'38'	
	call BYTESWAP
NoSwapBD8:
	movlw h'30'
	call BXORA ; b = (b xor a)
; Recupero di A
	movlw h'27'
	call SOTTR ; a = (a - s2i)
	bcf STATUS,RP0 ; Bank 0	
	movf 0x3F,w
	bsf STATUS,RP0 ; Bank 1
	movwf SEQCNT
	btfsc SEQCNT,6	
	goto RgtRotazAD8
; Rotazioni a sinistra
	movlw h'37'
	call LEFT_ROT 
	goto ContAD8
; Rotazioni a destra
RgtRotazAD8:
	movlw h'30'
	call RIGHT_ROT	
ContAD8:
	btfss SEQCNT,0
	goto NoSwapAD8
; Swap di A
	movlw h'30'	
	call BYTESWAP
NoSwapAD8:
	movlw h'38'
	call AXORB ; a = (a xor b)
	decfsz ITERAZ,1
	goto LoopDecifr8
; Fine della Decifratura	
	call STARTKEYS
	movlw h'27'
	call SOTTR ; a = (a - s0)
	movlw h'2F'
	call SOTTR ; b = (b - s1)
	return
;
;*****************************************************************
; DeSecret Keys A 8 BYTES S2i in 20-27 e S2i+1 in 28-2F
;*****************************************************************
;
DSECRETKEYS8:
	movlw h'10'
	movwf SEQCNT	
	movlw h'2F'	
	movwf FSR
	movf TBLNMB,w
	movwf PCLATH
LoopDSecret8:
	movf TBLADR,w
	call TABLE1
	movwf INDF
	decf TBLADR
	decf FSR
	decfsz SEQCNT,1
	goto LoopDSecret8
	movlw h'FF'
	subwf TBLADR,w
	btfss STATUS,Z
	return
	movlw h'02'
	subwf TBLNMB
	return
;
;*********************************************************************
; AXORB A N BYTES (xx-x+7) xor ((x+08)x-(x+08)x) = (xx-x+7)
;*********************************************************************
;
AXORB:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
LoopXorA:	
	movf INDF,w
	movwf BYTEVL
	movf NBYTES,w
	subwf FSR
	movf BYTEVL,w
	xorwf INDF
	movf NBYTES,w
	addwf FSR
	incf FSR
	decfsz SEQCNT,1
	goto LoopXorA
	return
;
;*********************************************************************
; BXORA A N BYTES (xx-xx) xor ((x+8)x-(x+8)x) = (xx-xx)
;*********************************************************************
;
BXORA:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
LoopXorB:	
	movf INDF,w
	movwf BYTEVL
	movf NBYTES,w
	addwf FSR
	movf BYTEVL,w
	xorwf INDF
	movf NBYTES,w
	subwf FSR
	incf FSR
	decfsz SEQCNT,1
	goto LoopXorB
	return
;
;************************************************************
; BYTESWAP
;************************************************************
;
BYTESWAP:
	movwf FSR
	movf NBYTES,w
	movwf COUNT1
SwapLoop:
	swapf INDF
	incf FSR
	decfsz COUNT1,1
	goto SwapLoop
	return
;
;************************************************************
; RIGHT_ROT A N BYTES 
;************************************************************
;
RIGHT_ROT:
	movwf FSR
	movf SEQCNT,w
	movwf COUNT2
	movlw h'3F'
	andwf COUNT2
LoopRgtRot:	
	movf NBYTES,w
	movwf COUNT1
	bcf STATUS,C ; azzera il Carry
RgtRot:
	rrf INDF
	incf FSR
	decfsz COUNT1,1
	goto RgtRot	
	rrf COUNT1 ; salva il valore del Carry in COUNT1 (che è azzerato)
	movf NBYTES,w
	subwf FSR ; riporta il puntatore al primo byte
	movf COUNT1,w ; recupera il Carry
	iorwf INDF
	decfsz COUNT2,1
	goto LoopRgtRot
	return
;
;************************************************************
; LEFT_ROT A N BYTES 
;************************************************************
;
LEFT_ROT:
	movwf FSR
	movf SEQCNT,w
	movwf COUNT2
	movlw h'3F'
	andwf COUNT2
LoopLftRot:	
	movf NBYTES,w
	movwf COUNT1
	bcf STATUS,C ; azzera il Carry
LftRot:
	rlf INDF
	decf FSR
	decfsz COUNT1,1
	goto LftRot	
	rlf COUNT1 ; salva il valore del Carry in COUNT1 (che è azzerato)
	movf NBYTES,w
	addwf FSR ; riporta il puntatore all'ultimo byte
	movf COUNT1,w ; recupera il Carry
	iorwf INDF
	decfsz COUNT2,1
	goto LoopLftRot
	return
;
;******************************************************************
; SOMMA A N BYTES (xx - xx+7) = (xx - xx+7) + ((x-10)x-(x-10)x)
;******************************************************************
;
SOMMA:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
	clrf OLDCARRY ; azzera eventuale riporto di operazioni precedenti
LoopSum:
	clrf NEWCARRY ; inizializza riporto di operazioni successive
	movf INDF,w
	movwf BYTEVL ; salva il secondo addendo
	movlw h'10' 
	addwf FSR ; punta al primo addendo
	movf BYTEVL,w ; recupera il secondo addendo
	addwf INDF,w ; somma in w primo e secondo addendo
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo 
	addwf OLDCARRY,w ; somma in w anche il Carry precedente
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo	 
	movwf INDF ; salva il risultato
	movf NEWCARRY,w
	movwf OLDCARRY ; adesso NEWCARRY diventa OLDCARRY
	movlw h'10'
	subwf FSR
	decf FSR
	decfsz SEQCNT,1
	goto LoopSum
	return
;
;******************************************************************
; COMPLEMENTO A DUE A N BYTES 
;******************************************************************
;
COMPL:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
	clrf OLDCARRY ; azzera eventuale riporto di operazioni precedenti
	movlw h'01'
LoopCompl:
	movwf BYTEVL ; salva il secondo addendo
	clrf NEWCARRY ; inizializza riporto di operazioni successive
	comf INDF ; esegue il complemento a uno del byte corrente
 	addwf INDF ; somma nel registro il byte '1'
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo
	movf OLDCARRY,w 
	addwf INDF ; somma nel registro anche il Carry precedente
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo	 
	movf NEWCARRY,w
	movwf OLDCARRY ; adesso NEWCARRY diventa OLDCARRY
	decf FSR
	movlw h'00' ; byte a zero da sommare per il complemento a due
	decfsz SEQCNT,1
	goto LoopCompl
	return
;
;************************************************************
; SOTTR A N BYTES (xx-xx) - ((x-10)x-(x-10)x) = (xx-xx)
;************************************************************
;
SOTTR:
	movwf COMPLRF ; salva indirizzo sottraendo	
	call COMPL ; esegue il complemento a due del sottraendo
	movf COMPLRF,w ; recupera indirizzo sottraendo
	call SOMMA ; esegue la somma
	return
;************************************************************
; START KEYS (S0 S1) 
;************************************************************
STARTKEYS:	
	bcf STATUS,RP0 ; Bank 0;s[0] = 'CB8196CA68D52AFC'
	movlw h'CB'
	movwf 0x20
	movlw h'81'
	movwf 0x21
	movlw h'96'
	movwf 0x22
	movlw h'CA'
	movwf 0x23
	movlw h'68'
	movwf 0x24
	movlw h'D5'
	movwf 0x25
	movlw h'2A'
	movwf 0x26
	movlw h'FC'
	movwf 0x27
;s[1] = '06F0886EC3C1ED6D'
	movlw h'06'
	movwf 0x28
	movlw h'F0'
	movwf 0x29
	movlw h'88'
	movwf 0x2A
	movlw h'6E'
	movwf 0x2B
	movlw h'C3'
	movwf 0x2C
	movlw h'C1'
	movwf 0x2D
	movlw h'ED'
	movwf 0x2E
	movlw h'6D'
	movwf 0x2F
	bsf STATUS,RP0 ; Bank 1
	return
;
; ************************************************
; ROUTINES DI GESTIONE
; ************************************************
;
;***********************************************
; DELAY Routine max 196,65 msec, min 0,771 msec
;***********************************************
;
DELAY_MAX:
	movlw h'FF'
DELAY:
	movwf COUNT2
Dly2:
	movlw h'FF'
	movwf COUNT1
Dly1:
	decfsz COUNT1,1
	goto Dly1
	decfsz COUNT2,1
	goto Dly2	
	return
;
;****************************************************
; LDELAY Routine lungo ritardo 1 ciclo circa 196 msec; max 49.8 sec circa
;****************************************************
;
LDELAY_STD:
	movlw h'02'
LDELAY:
	movwf ITERAZ
Dly3:
	call DELAY_MAX
	decfsz ITERAZ,1
	goto Dly3
	return
;
;*****************************************************************
; SEQVALID: Confronta SEQ1(xx) - SEQ2(xx+16) SEQCNT:Lunghezza Seq.
; CONFR = 0 non validata; CONFR = 1 validata
;*****************************************************************
;
SEQVALID:
	movwf FSR
	clrf CONFR
SeqValLoop:	
	movf INDF,w
	movwf BYTEVL
	movlw h'10'
	addwf FSR
	movf BYTEVL,w
	subwf INDF,w
	btfss STATUS,Z ;se risultato =0 Z=1 salta (e continua)
	return ; ritorna con CONFR = 0: non validata
	movlw h'10'
	subwf FSR
	incf FSR
	decfsz SEQCNT,1
	goto SeqValLoop
	incf CONFR ; ritorna con CONFR = 1: validata
	return
;
;*****************************************************************
; ZEROTEST: Confronta SEQ con zero SEQCNT:Lunghezza Seq.
; CONFR = 0 sequenza non zero; CONFR = 1 sequenza zero
;*****************************************************************
;
ZEROTEST:
	movwf FSR
	clrf CONFR
ZeroTestLoop:	
	movf INDF,w
	btfss STATUS,Z ;se risultato =0 Z=1 salta (e continua)
	return ; ritorna con CONFR = 0: sequenza non zero
	incf FSR
	decfsz SEQCNT,1
	goto ZeroTestLoop
	incf CONFR ; ritorna con CONFR = 1: sequenza zero
	return
;
;********************************************************************************
; COUNTER_COPY: 
;********************************************************************************
;
COUNTER_COPY:
; Salva il contatore in 50-53
	movlw h'04'
	movwf SEQCNT
	movlw h'30'
	movwf FSR
CntCpyLoop:
	movf INDF,w
	movwf BYTEVL
	movlw h'20'
	addwf FSR
	movf BYTEVL,w
	movwf INDF
	movlw h'20'
	subwf FSR
	incf FSR
	decfsz SEQCNT,1
	goto CntCpyLoop
	return
;
;***********************************************************************
; COUNTER_RECOV: carica in 40-43 il contatore della chiave puntata da 3F
; prelevandolo F4-FE della EEPROM 
;***********************************************************************
;
COUNTER_RECOV:
 	movlw h'40' 
	movwf TBLADR
	movlw h'04'
	movwf SEQCNT
	bcf STATUS,RP0 ; Bank 0
	movf CMDRCV,w
	bsf STATUS,RP0 ; Bank 1
	movwf EEADR
	movf TBLADR,w
	call INTEE_RD
	return
;
;********************************************************************************
; COUNTER_SAVE: Salva il contatore nella EEPROM 
; (senza l'ultimo byte) 
;********************************************************************************
;
COUNTER_SAVE:
 	movlw h'04'
	movwf SEQCNT
	bcf STATUS,RP0 ; Bank 0
	movf CMDRCV,w
	bsf STATUS,RP0 ; Bank 1
	movwf EEADR
	movlw h'30'
	call INTEE_WR	
	return
;
;***************************************************************
; LOCKID_RECOV: carica in 44-4E il codice serratura
; prelevandolo F4-FE della EEPROM 
;***************************************************************
;
LOCKID_RECOV:
 	movlw h'44' 
	movwf TBLADR
	movlw h'0B'
	movwf SEQCNT	
	movlw h'F4'
	movwf EEADR
	movf TBLADR,w
	call INTEE_RD
	return
;
;********************************************************************************
; COUNTERS_RESET: Azzera tutti i contatori della EEPROM  
;********************************************************************************
;
COUNTERS_RESET:
 	movlw h'3C'
	movwf BYTCNT
	bcf STATUS,RP0 ; Bank 0
	clrf CMDRCV
	bsf STATUS,RP0 ; Bank 1	
CntRstLoop:
	call COUNTER_SAVE
	movlw h'04'
	bcf STATUS,RP0 ; Bank 0
	addwf CMDRCV,1
	bsf STATUS,RP0 ; Bank 1	
	decfsz BYTCNT,1
	goto CntRstLoop	
	return
;
;********************************************************************************
; LOCKID_SAVE: Salva il Lock Id nella EEPROM  
;********************************************************************************
;
LOCKID_SAVE:
 	movlw h'0B'
	movwf SEQCNT
	movlw h'F4'
	movwf EEADR
	movlw h'34'
	call INTEE_WR	
	return
;
;******************************************
; EEREAD Routine: indirizzo in w
;******************************************
;
EEREAD:
	movwf EEADR ;Address to read
	bsf EECON1,RD ;EE Read
	movf EEDAT,W ;risultato in w
	return
;
;*************************************************************
; EEWRITE Routine: byte in EEDAT, indirizzo in EEADR  
;*************************************************************
;
EEWRITE:
	bsf EECON1,WREN ;Enable write
	movlw h'55' ;Unlock write
	movwf EECON2
	movlw h'AA'
	movwf EECON2
	bsf EECON1,WR ;Start the write
	movlw h'0A' ; 06 è il minimo
	call DELAY
	return
;
;********************************************************************************
; INTEE_WR ROUTINE da RAM a EEPROM, lunghezza sequenza in SEQCNT 
;********************************************************************************
;
INTEE_WR:
	movwf FSR
IntEEWrLoop:
	movf INDF,w
	movwf EEDAT
	call EEWRITE
	incf FSR
	incf EEADR
	decfsz SEQCNT,1
	goto IntEEWrLoop
	return
;
;********************************************************************************
; INTEE_RD ROUTINE da EEPROM a RAM, lunghezza sequenza in SEQCNT 
;********************************************************************************
;
INTEE_RD:
	movwf FSR
IntEERdLoop:
	bsf EECON1,RD ;EE Read
	movf EEDAT,W ;risultato in w	
	movwf INDF
	incf FSR
	incf EEADR
	decfsz SEQCNT,1
	goto IntEERdLoop
	return
;
;******************************************************************************
	end ; directive 'end of program'
;******************************************************************************
;

Da ultimo i codici di programmazione del dispositivo Telecomando di Fig.9, anch'esso basato sul microcontrollore PIC16F684.

;**********************************************************************
;   Algoritmo RC5-64-32-528			   					              *
;**********************************************************************
;                                                                     *
;    Filename:	    P16F684_Key64.asm                                 *
;    Date:                                                            *
;    File Version: Versione 1.0                                       *
;                                                                     *
;    Author:  InTeAS Web Master                                       *
;    Company: https://www.inteas.it                                   *
;                                                                     * 
;                                                                     *
;**********************************************************************
;                                                                     *
;    Files Required: P16F684.INC                                      *
;                                                                     *
;**********************************************************************
;                                                                     *
;    Notes:                                                           *
;                                                                     *
;**********************************************************************
;
list p=16f684 ; list directive to define processor
#include <P16F684.inc> ; processor specific variable definitions
__CONFIG    _CP_OFF & _CPD_OFF & _BOD_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_ON & _FCMEN_OFF & _IESO_OFF
; '__CONFIG' directive is used to embed configuration word within .asm file.
; The lables following the directive are located in the respective .inc file. 
; See respective data sheet for additional information on configuration word.
;
;**************
; Mappa EEPROM
;**************
;
; 00-03 Contatore di chiave
; 04 Flag di inizializzazione
; 05-FF non usati
;
;******************************
; DEFINIZIONE VARIABILI LOCALI
;******************************
;
; Interval 0x20 - 0x7F , Bank 0
; Interval 0xA0 - 0xBF , Bank 1
;
;**********************
; Bank0
;**********************
;
; 20-27 S_2i 
; 28-2F S_2i+1
; 30-37 A, KrA
; 38-3F B, KrB
;
;**********************
; Bank1
;**********************
;
COUNT1        EQU  0xBF
COUNT2        EQU  0xBE
SEQCNT        EQU  0xBD
BYTCNT		  EQU  0xBC
TBLNMB        EQU  0xBB
TBLADR        EQU  0xBA
BYTEVL		  EQU  0xB9
ITERAZ        EQU  0xB8
OLDCARRY	  EQU  0xB7
NEWCARRY      EQU  0xB6
COMPLRF		  EQU  0xB5
MASK 		  EQU  0xB4
DLCNT1		  EQU  0xB3
DLCNT2		  EQU  0xB2
UNOCNT        EQU  0xB1
NBYTES        EQU  0xB0
CONFR         EQU  0xAE
;
;**********************************************************************
	ORG		0x000			; processor reset vector
	goto	Init			; go to beginning of program
;
	ORG		0x004			; interrupt vector location
	goto 	Init
;
Init:
;
; OPTION Register, on reset all bits = 1
	; bit 7 (NOT_RAPU) Weak Pull-Ups Disabled	
	; bit 6 (INTEDG) Interrupt Edge Select
	; bit 5 (T0CS) Timer0 Source Selection: 1= T0CKI Transition (default), 0= Internal Instruction (CLKOUT) 
	; bit 4 (T0SE) Timer0 Source Edge Selection: 1 = H-to-L (default), 0= L-to-H  
	; bit 3 (PSA) Prescaler Assignment: 1= to WDT (default), 0= to Timer0	
	; bits 2:0 (PS2,PS1,PS0) Prescaler Rate Selection: 1:128 default
;
	movlw b'11011111' ; T0CS= 0 : Internal Timer0 (RC5 can be I/O line)
;
	bsf STATUS,RP0 ; Bank 1		
	movwf OPTION_REG
;
; I/O Summary
;
; PORTA,5 OUTPUT (pin  2) : Segnale Tx
; PORTA,4 OUTPUT (pin  3) : Probe Led (attivo su 0)
; PORTA,3 INPUT  (pin  4) : NC
; PORTA,2 INPUT  (pin 11) : NC
; PORTA,1 INPUT  (pin 12) : NC
; PORTA,0 INPUT  (pin 13) : NC
;
; PORTC,5 INPUT  (pin  5) : NC
; PORTC,4 INPUT  (pin  6) : NC
; PORTC,3 INPUT  (pin  7) : NC
; PORTC,2 INPUT  (pin  8) : NC
; PORTC,1 INPUT  (pin  9) : NC
; PORTC,0 INPUT  (pin 10) : NC
;
;
; *******************************
; Set of the PORTA I/O (bit 5:0)
; *******************************
;
	bcf STATUS,RP0 ; Bank 0
	movlw h'07' ; Set RA<2:0> to digital I/O
	movwf CMCON0
	bsf STATUS,RP0 ; Bank 1
	clrf ANSEL ; Digital I/O only: no analogical function
	movlw h'00000000'
	movwf IOCA ; Interrupt on change (disabilitato se = 0)
; 1=input 0=output	
	movlw b'11001111'
	movwf TRISA	; write in TRISA register	
;
; *******************************
; Set of the PORTC I/O (bit 5:0)
; *******************************
;
	movlw b'11111111'
	movwf TRISC	   ; write in TRISC register
;
	bcf STATUS,RP0 ; Bank 0
	bcf PORTA,5 ; segnale Tx basso
	bsf PORTA,4 ; Probe Led spento
;
	bsf STATUS,RP0 ; Bank 1 condizione normale di funzionamento
	call DELAY_STD
;
Main:
;	
; Inizializzazione su pulsante premuto
;
	call AB_RECOV
	movlw h'08'
	movwf NBYTES ; numero bytes	
	call CIFRATURA8 ; esegue la cifratura in 30-3F
MainLoop:		
	bcf STATUS,RP0 ; Bank 0
	bsf PORTA,5; Trasmette start bit
	bcf PORTA,4 ; Probe Led acceso
	bsf STATUS,RP0 ; Bank 1
	movlw h'FF'
	call BDELAY
	movlw h'60'
	call BDELAY
	movlw h'10'
	movwf SEQCNT
	movlw h'30'
	call BUFFER_TX
	bcf STATUS,RP0 ; Bank 0
	goto MainLoop
;
;*********************************************
; PASSWORD GENERATRICE DI ESEMPIO
;*********************************************
;
; 1CA97A224432B78088A91048A5C739C54BAB2C8400372600B8A37C0F825A5386F65F62368CDBF3A694
; 92DB949DE0D7D069C35640632C7811A6C03C7651A1D070414A8E117B18F5FF9C971568F491AF16D7C7
; 52584B8130DC5B37C37A540E9EC2945289FA2E424411FDFEA903918119483687A82D7C40A0C8B2D3AC
; C3DF6E7A1541885C9090E2FE1652CF87FF35A9CD87456D13944398DD26192672AF8D588D9AD0343117
; 3C581C114F3BA5B849211A7AC13009833B9AA277EC95A54C943303F20E77972C8F631E0E5565B05D85
; 3D7BCD2AF969D3C38E10906FCE03BD6A3E4EA2176A9A887582F1CC81901D907C8ACC36CEC8124EE2BB
; 8146C83F2FB2E0C2E621AF57E4EAE8DE641BA14027631FDB1C4E20C5E9FFC8DA14A73229122122B7D5
; F519E2DA9D9DC8CCF394AFC8FFF34ADA97DC4E70958E11DBB1424AAA55B0738ABDC478E46212A00FC7
; 617599265EF717B621CCBD2125F780945DDEA454AF2EA2D74A34262770C21A8A862EC61E0022D09D00
; ADFA815F33BB32866E6713DB85639E8EBB8B3E129D3FA312F7B90876F495DFC9CC0BB7ED630FCDFD12
; 8D67FFA78059D7AAC3965A0A0C49D25C2C09D136779049E4C14555745CF53352B3C69ECF63898B6A75
; 991CAEC19270ECBF7E1095D2E1E745F7DFA42B53CE987B6B0881CE0A802C3018EDA109A8FACFCBEA5B
; 9FDC8C18DB0E131E27DF124B2B2C5E101E5D162D968193F815A2A09B5D692D8C450D81D8
;
;*********************************************
;
;************************
;TABLE 1
;************************
	ORG		0x0FF
TABLE1:
	addwf PCL
;s[2] = 'DAD0C6754A89DB4C'
	retlw h'DA'
	retlw h'D0'
	retlw h'C6'
	retlw h'75'
	retlw h'4A'
	retlw h'89'
	retlw h'DB'
	retlw h'4C'
;s[3] = 'BF234DDC889B7786'
	retlw h'BF'
	retlw h'23'
	retlw h'4D'
	retlw h'DC'
	retlw h'88'
	retlw h'9B'
	retlw h'77'
	retlw h'86'
;s[4] = 'B71A1DA4AA42D6B4'
	retlw h'B7'
	retlw h'1A'
	retlw h'1D'
	retlw h'A4'
	retlw h'AA'
	retlw h'42'
	retlw h'D6'
	retlw h'B4'
;s[5] = 'DF0B16BA7A2A7E85'
	retlw h'DF'
	retlw h'0B'
	retlw h'16'
	retlw h'BA'
	retlw h'7A'
	retlw h'2A'
	retlw h'7E'
	retlw h'85'
;s[6] = '7EE0AC20F2373D33'
	retlw h'7E'
	retlw h'E0'
	retlw h'AC'
	retlw h'20'
	retlw h'F2'
	retlw h'37'
	retlw h'3D'
	retlw h'33'
;s[7] = '2BE71B26488E0195'
	retlw h'2B'
	retlw h'E7'
	retlw h'1B'
	retlw h'26'
	retlw h'48'
	retlw h'8E'
	retlw h'01'
	retlw h'95'
;s[8] = '34065D0075EF1A1A'
	retlw h'34'
	retlw h'06'
	retlw h'5D'
	retlw h'00'
	retlw h'75'
	retlw h'EF'
	retlw h'1A'
	retlw h'1A'
;s[9] = '9771D6B39B0DBF6B'
	retlw h'97'
	retlw h'71'
	retlw h'D6'
	retlw h'B3'
	retlw h'9B'
	retlw h'0D'
	retlw h'BF'
	retlw h'6B'
;s[10] = '3A41B44288F99546'
	retlw h'3A'
	retlw h'41'
	retlw h'B4'
	retlw h'42'
	retlw h'88'
	retlw h'F9'
	retlw h'95'
	retlw h'46'
;s[11] = 'B01442143AF84396'
	retlw h'B0'
	retlw h'14'
	retlw h'42'
	retlw h'14'
	retlw h'3A'
	retlw h'F8'
	retlw h'43'
	retlw h'96'
;s[12] = '9D61E9B94DD9F6AF'
	retlw h'9D'
	retlw h'61'
	retlw h'E9'
	retlw h'B9'
	retlw h'4D'
	retlw h'D9'
	retlw h'F6'
	retlw h'AF'
;s[13] = 'C2652CFD3DCE2FD2'
	retlw h'C2'
	retlw h'65'
	retlw h'2C'
	retlw h'FD'
	retlw h'3D'
	retlw h'CE'
	retlw h'2F'
	retlw h'D2'
;s[14] = 'C714C9C1CEA41830'
	retlw h'C7'
	retlw h'14'
	retlw h'C9'
	retlw h'C1'
	retlw h'CE'
	retlw h'A4'
	retlw h'18'
	retlw h'30'
;s[15] = 'C686999FEE730C53'
	retlw h'C6'
	retlw h'86'
	retlw h'99'
	retlw h'9F'
	retlw h'EE'
	retlw h'73'
	retlw h'0C'
	retlw h'53'
;s[16] = '1AF09EDEA3EF1DF7'
	retlw h'1A'
	retlw h'F0'
	retlw h'9E'
	retlw h'DE'
	retlw h'A3'
	retlw h'EF'
	retlw h'1D'
	retlw h'F7'
;s[17] = 'C9538AF72A387415'
	retlw h'C9'
	retlw h'53'
	retlw h'8A'
	retlw h'F7'
	retlw h'2A'
	retlw h'38'
	retlw h'74'
	retlw h'15'
;s[18] = 'D2D942C4BA82A0BC'
	retlw h'D2'
	retlw h'D9'
	retlw h'42'
	retlw h'C4'
	retlw h'BA'
	retlw h'82'
	retlw h'A0'
	retlw h'BC'
;s[19] = '9B7A9B98C73D486B'
	retlw h'9B'
	retlw h'7A'
	retlw h'9B'
	retlw h'98'
	retlw h'C7'
	retlw h'3D'
	retlw h'48'
	retlw h'6B'
;s[20] = '07DC150E9B6D874B'
	retlw h'07'
	retlw h'DC'
	retlw h'15'
	retlw h'0E'
	retlw h'9B'
	retlw h'6D'
	retlw h'87'
	retlw h'4B'
;s[21] = '64F5A0CB3F105E4C'
	retlw h'64'
	retlw h'F5'
	retlw h'A0'
	retlw h'CB'
	retlw h'3F'
	retlw h'10'
	retlw h'5E'
	retlw h'4C'
;s[22] = '49D58C7504D691C7'
	retlw h'49'
	retlw h'D5'
	retlw h'8C'
	retlw h'75'
	retlw h'04'
	retlw h'D6'
	retlw h'91'
	retlw h'C7'
;s[23] = '83416F9E11060720'
	retlw h'83'
	retlw h'41'
	retlw h'6F'
	retlw h'9E'
	retlw h'11'
	retlw h'06'
	retlw h'07'
	retlw h'20'
;s[24] = '486BD4265E984FC9'
	retlw h'48'
	retlw h'6B'
	retlw h'D4'
	retlw h'26'
	retlw h'5E'
	retlw h'98'
	retlw h'4F'
	retlw h'C9'
;s[25] = 'EC93478FB7723A82'
	retlw h'EC'
	retlw h'93'
	retlw h'47'
	retlw h'8F'
	retlw h'B7'
	retlw h'72'
	retlw h'3A'
	retlw h'82'
;s[26] = '65C4D61723065581'
	retlw h'65'
	retlw h'C4'
	retlw h'D6'
	retlw h'17'
	retlw h'23'
	retlw h'06'
	retlw h'55'
	retlw h'81'
;s[27] = 'E361221076C5A87C'
	retlw h'E3'
	retlw h'61'
	retlw h'22'
	retlw h'10'
	retlw h'76'
	retlw h'C5'
	retlw h'A8'
	retlw h'7C'
;s[28] = 'DBA9833D724F27C9'
	retlw h'DB'
	retlw h'A9'
	retlw h'83'
	retlw h'3D'
	retlw h'72'
	retlw h'4F'
	retlw h'27'
	retlw h'C9'
;s[29] = '5596A65AE9EEFE1A'
	retlw h'55'
	retlw h'96'
	retlw h'A6'
	retlw h'5A'
	retlw h'E9'
	retlw h'EE'
	retlw h'FE'
	retlw h'1A'
;s[30] = '704AEC3011904717'
	retlw h'70'
	retlw h'4A'
	retlw h'EC'
	retlw h'30'
	retlw h'11'
	retlw h'90'
	retlw h'47'
	retlw h'17'
;s[31] = '5C7ACECFA4B36D27'
	retlw h'5C'
	retlw h'7A'
	retlw h'CE'
	retlw h'CF'
	retlw h'A4'
	retlw h'B3'
	retlw h'6D'
	retlw h'27'
;s[32] = 'B75059854AF527E3'
	retlw h'B7'
	retlw h'50'
	retlw h'59'
	retlw h'85'
	retlw h'4A'
	retlw h'F5'
	retlw h'27'
	retlw h'E3'
;s[33] = '872B26243F2D530F'
	retlw h'87'
	retlw h'2B'
	retlw h'26'
	retlw h'24'
	retlw h'3F'
	retlw h'2D'
	retlw h'53'
	retlw h'0F'
;
;************************************************************
; ROUTINES COMUNI 
;************************************************************
	ORG		0x200
	nop
	nop
;************************
;TABLE 2
;************************
	ORG		0x2FF
TABLE2:
	addwf PCL;s[34] = '831CC87D65F1473A'
	retlw h'83'
	retlw h'1C'
	retlw h'C8'
	retlw h'7D'
	retlw h'65'
	retlw h'F1'
	retlw h'47'
	retlw h'3A'
;s[35] = '3359FF516A534F83'
	retlw h'33'
	retlw h'59'
	retlw h'FF'
	retlw h'51'
	retlw h'6A'
	retlw h'53'
	retlw h'4F'
	retlw h'83'
;s[36] = 'C2FEC52B1A49DF0B'
	retlw h'C2'
	retlw h'FE'
	retlw h'C5'
	retlw h'2B'
	retlw h'1A'
	retlw h'49'
	retlw h'DF'
	retlw h'0B'
;s[37] = 'A34CDB8977799710'
	retlw h'A3'
	retlw h'4C'
	retlw h'DB'
	retlw h'89'
	retlw h'77'
	retlw h'79'
	retlw h'97'
	retlw h'10'
;s[38] = '607D835653B498FB'
	retlw h'60'
	retlw h'7D'
	retlw h'83'
	retlw h'56'
	retlw h'53'
	retlw h'B4'
	retlw h'98'
	retlw h'FB'
;s[39] = '64557D6DEE68B8E3'
	retlw h'64'
	retlw h'55'
	retlw h'7D'
	retlw h'6D'
	retlw h'EE'
	retlw h'68'
	retlw h'B8'
	retlw h'E3'
;s[40] = 'B6AA6AE220EEF5EE'
	retlw h'B6'
	retlw h'AA'
	retlw h'6A'
	retlw h'E2'
	retlw h'20'
	retlw h'EE'
	retlw h'F5'
	retlw h'EE'
;s[41] = '53207F2D5579AA9D'
	retlw h'53'
	retlw h'20'
	retlw h'7F'
	retlw h'2D'
	retlw h'55'
	retlw h'79'
	retlw h'AA'
	retlw h'9D'
;s[42] = 'BDEAAB28AE597A66'
	retlw h'BD'
	retlw h'EA'
	retlw h'AB'
	retlw h'28'
	retlw h'AE'
	retlw h'59'
	retlw h'7A'
	retlw h'66'
;s[43] = '0D2F035351EFB50C'
	retlw h'0D'
	retlw h'2F'
	retlw h'03'
	retlw h'53'
	retlw h'51'
	retlw h'EF'
	retlw h'B5'
	retlw h'0C'
;s[44] = 'C54FB7AD19DB5832'
	retlw h'C5'
	retlw h'4F'
	retlw h'B7'
	retlw h'AD'
	retlw h'19'
	retlw h'DB'
	retlw h'58'
	retlw h'32'
;s[45] = 'F72D8E48F4BFCC64'
	retlw h'F7'
	retlw h'2D'
	retlw h'8E'
	retlw h'48'
	retlw h'F4'
	retlw h'BF'
	retlw h'CC'
	retlw h'64'
;s[46] = 'AB3E99FFF5CD1185'
	retlw h'AB'
	retlw h'3E'
	retlw h'99'
	retlw h'FF'
	retlw h'F5'
	retlw h'CD'
	retlw h'11'
	retlw h'85'
;s[47] = '299BBDF630DFEC2A'
	retlw h'29'
	retlw h'9B'
	retlw h'BD'
	retlw h'F6'
	retlw h'30'
	retlw h'DF'
	retlw h'EC'
	retlw h'2A'
;s[48] = 'EFB3E9479BA57493'
	retlw h'EF'
	retlw h'B3'
	retlw h'E9'
	retlw h'47'
	retlw h'9B'
	retlw h'A5'
	retlw h'74'
	retlw h'93'
;s[49] = '30A00D9B7A9E3E33'
	retlw h'30'
	retlw h'A0'
	retlw h'0D'
	retlw h'9B'
	retlw h'7A'
	retlw h'9E'
	retlw h'3E'
	retlw h'33'
;s[50] = '8CB1FD062928979F'
	retlw h'8C'
	retlw h'B1'
	retlw h'FD'
	retlw h'06'
	retlw h'29'
	retlw h'28'
	retlw h'97'
	retlw h'9F'
;s[51] = '871E9FC0AD2ABFBB'
	retlw h'87'
	retlw h'1E'
	retlw h'9F'
	retlw h'C0'
	retlw h'AD'
	retlw h'2A'
	retlw h'BF'
	retlw h'BB'
;s[52] = 'C3E5C992DDD5E0D5'
	retlw h'C3'
	retlw h'E5'
	retlw h'C9'
	retlw h'92'
	retlw h'DD'
	retlw h'D5'
	retlw h'E0'
	retlw h'D5'
;s[53] = 'ECCCF82235DA4103'
	retlw h'EC'
	retlw h'CC'
	retlw h'F8'
	retlw h'22'
	retlw h'35'
	retlw h'DA'
	retlw h'41'
	retlw h'03'
;s[54] = '2F26883D23817BD3'
	retlw h'2F'
	retlw h'26'
	retlw h'88'
	retlw h'3D'
	retlw h'23'
	retlw h'81'
	retlw h'7B'
	retlw h'D3'
;s[55] = '47166BD90F01D8B9'
	retlw h'47'
	retlw h'16'
	retlw h'6B'
	retlw h'D9'
	retlw h'0F'
	retlw h'01'
	retlw h'D8'
	retlw h'B9'
;s[56] = 'BAB9F1B89E4573CE'
	retlw h'BA'
	retlw h'B9'
	retlw h'F1'
	retlw h'B8'
	retlw h'9E'
	retlw h'45'
	retlw h'73'
	retlw h'CE'
;s[57] = 'DA6D99F440E03581'
	retlw h'DA'
	retlw h'6D'
	retlw h'99'
	retlw h'F4'
	retlw h'40'
	retlw h'E0'
	retlw h'35'
	retlw h'81'
;s[58] = '2594A813A786AA14'
	retlw h'25'
	retlw h'94'
	retlw h'A8'
	retlw h'13'
	retlw h'A7'
	retlw h'86'
	retlw h'AA'
	retlw h'14'
;s[59] = '29AC9948B086A498'
	retlw h'29'
	retlw h'AC'
	retlw h'99'
	retlw h'48'
	retlw h'B0'
	retlw h'86'
	retlw h'A4'
	retlw h'98'
;s[60] = '7EC4D8BAC0BFA46A'
	retlw h'7E'
	retlw h'C4'
	retlw h'D8'
	retlw h'BA'
	retlw h'C0'
	retlw h'BF'
	retlw h'A4'
	retlw h'6A'
;s[61] = '21637EE089A13E62'
	retlw h'21'
	retlw h'63'
	retlw h'7E'
	retlw h'E0'
	retlw h'89'
	retlw h'A1'
	retlw h'3E'
	retlw h'62'
;s[62] = '04B070B1A9F7CB67'
	retlw h'04'
	retlw h'B0'
	retlw h'70'
	retlw h'B1'
	retlw h'A9'
	retlw h'F7'
	retlw h'CB'
	retlw h'67'
;s[63] = '52492DE3CEA59C25'
	retlw h'52'
	retlw h'49'
	retlw h'2D'
	retlw h'E3'
	retlw h'CE'
	retlw h'A5'
	retlw h'9C'
	retlw h'25'
;s[64] = 'A8C971E85214AE35'
	retlw h'A8'
	retlw h'C9'
	retlw h'71'
	retlw h'E8'
	retlw h'52'
	retlw h'14'
	retlw h'AE'
	retlw h'35'
;s[65] = 'D0B5FDA1EFAECB70'
	retlw h'D0'
	retlw h'B5'
	retlw h'FD'
	retlw h'A1'
	retlw h'EF'
	retlw h'AE'
	retlw h'CB'
	retlw h'70'
;
;************************
;FINE TABLE
;************************ 
;
;************************************************************
; ROUTINES COMUNI E DI CIFRATURA/DECIFRATURA (400-7FF)
;************************************************************
	ORG		0x400
;
;************************************************************
; CIFRATURA a 8 bytes
;************************************************************
;
CIFRATURA8:
	movlw h'01'
	movwf TBLNMB
	movlw h'00'
	movwf TBLADR
	movlw h'20'
	movwf ITERAZ
; Inizio della cifratura	
	call STARTKEYS
	movlw h'27'
	call SOMMA ; a = (a + s0)
	movlw h'2F'
	call SOMMA ; b = (b + s1)
LoopCifr8:
	call SECRETKEYS8
; Aggiornamento di A	
	movlw h'38'
	call AXORB ; a = (a xor b)
	bcf STATUS,RP0 ; Bank 0	
	movf 0x3F,w
	bsf STATUS,RP0 ; Bank 1
	movwf SEQCNT
	btfss SEQCNT,0
	goto NoSwapA8
; Swap di A
	movlw h'30'	
	call BYTESWAP
NoSwapA8:
	btfss SEQCNT,6	
	goto RgtRotazA8
; Rotazioni a sinistra
	movlw h'37'
	call LEFT_ROT 
	goto ContA8
; Rotazioni a destra
RgtRotazA8:
	movlw h'30'
	call RIGHT_ROT	
ContA8:
	movlw h'27'
	call SOMMA ; a = (a + s2i)
; Aggiornamento di B
	movlw h'30'
	call BXORA ; b = (b xor a)
	bcf STATUS,RP0 ; Bank 0	
	movf 0x37,w
	bsf STATUS,RP0 ; Bank 1
	movwf SEQCNT
	btfss SEQCNT,0
	goto NoSwapB8
; Swap di B
	movlw h'38'	
	call BYTESWAP
NoSwapB8:
	btfss SEQCNT,6	
	goto RgtRotazB8
; Rotazioni a sinistra
	movlw h'3F'
	call LEFT_ROT 
	goto ContB8
; Rotazioni a destra
RgtRotazB8:
	movlw h'38'
	call RIGHT_ROT
ContB8:
	movlw h'2F'
	call SOMMA ; b = (b + s2i+1)
	decfsz ITERAZ,1
	goto LoopCifr8
	return
;*****************************************************************
; Secret Keys a 8 bytes S2i in 20-27 e S2i+1 in 28-2F
;*****************************************************************
SECRETKEYS8:
	movlw h'10'
	movwf SEQCNT
	movlw h'20'
	movwf FSR
	movf TBLNMB,w
	movwf PCLATH
LoopSecret8:
	movf TBLADR,w
	call TABLE1
	movwf INDF
	incf TBLADR
	incf FSR
	decfsz SEQCNT,1
	goto LoopSecret8
	movf TBLADR,w
	btfss STATUS,Z
	return
	movlw h'02'
	addwf TBLNMB
	return
;*********************************************************************
; AXORB A N BYTES (xx-x+7) xor ((x+08)x-(x+08)x) = (xx-x+7)
;*********************************************************************
AXORB:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
LoopXorA:	
	movf INDF,w
	movwf BYTEVL
	movf NBYTES,w
	subwf FSR
	movf BYTEVL,w
	xorwf INDF
	movf NBYTES,w
	addwf FSR
	incf FSR
	decfsz SEQCNT,1
	goto LoopXorA
	return
;*********************************************************************
; BXORA A N BYTES (xx-xx) xor ((x+8)x-(x+8)x) = (xx-xx)
;*********************************************************************
BXORA:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
LoopXorB:	
	movf INDF,w
	movwf BYTEVL
	movf NBYTES,w
	addwf FSR
	movf BYTEVL,w
	xorwf INDF
	movf NBYTES,w
	subwf FSR
	incf FSR
	decfsz SEQCNT,1
	goto LoopXorB
	return
;************************************************************
; BYTESWAP
;************************************************************
BYTESWAP:
	movwf FSR
	movf NBYTES,w
	movwf COUNT1
SwapLoop:
	swapf INDF
	incf FSR
	decfsz COUNT1,1
	goto SwapLoop
	return
;************************************************************
; RIGHT_ROT A N BYTES 
;************************************************************
RIGHT_ROT:
	movwf FSR
	movf SEQCNT,w
	movwf COUNT2
	movlw h'3F'
	andwf COUNT2
LoopRgtRot:	
	movf NBYTES,w
	movwf COUNT1
	bcf STATUS,C ; azzera il Carry
RgtRot:
	rrf INDF
	incf FSR
	decfsz COUNT1,1
	goto RgtRot	
	rrf COUNT1 ; salva il valore del Carry in COUNT1 (che è azzerato)
	movf NBYTES,w
	subwf FSR ; riporta il puntatore al primo byte
	movf COUNT1,w ; recupera il Carry
	iorwf INDF
	decfsz COUNT2,1
	goto LoopRgtRot
	return
;************************************************************
; LEFT_ROT A N BYTES 
;************************************************************
LEFT_ROT:
	movwf FSR
	movf SEQCNT,w
	movwf COUNT2
	movlw h'3F'
	andwf COUNT2
LoopLftRot:	
	movf NBYTES,w
	movwf COUNT1
	bcf STATUS,C ; azzera il Carry
LftRot:
	rlf INDF
	decf FSR
	decfsz COUNT1,1
	goto LftRot	
	rlf COUNT1 ; salva il valore del Carry in COUNT1 (che è azzerato)
	movf NBYTES,w
	addwf FSR ; riporta il puntatore all'ultimo byte
	movf COUNT1,w ; recupera il Carry
	iorwf INDF
	decfsz COUNT2,1
	goto LoopLftRot
	return
;******************************************************************
; SOMMA A N BYTES (xx - xx+7) = (xx - xx+7) + ((x-10)x-(x-10)x)
;******************************************************************
SOMMA:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
	clrf OLDCARRY ; azzera eventuale riporto di operazioni precedenti
LoopSum:
	clrf NEWCARRY ; inizializza riporto di operazioni successive
	movf INDF,w
	movwf BYTEVL ; salva il secondo addendo
	movlw h'10' 
	addwf FSR ; punta al primo addendo
	movf BYTEVL,w ; recupera il secondo addendo
	addwf INDF,w ; somma in w primo e secondo addendo
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo 
	addwf OLDCARRY,w ; somma in w anche il Carry precedente
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo	 
	movwf INDF ; salva il risultato
	movf NEWCARRY,w
	movwf OLDCARRY ; adesso NEWCARRY diventa OLDCARRY
	movlw h'10'
	subwf FSR
	decf FSR
	decfsz SEQCNT,1
	goto LoopSum
	return
;******************************************************************
; COMPLEMENTO A DUE A N BYTES 
;******************************************************************
COMPL:	
	movwf FSR
	movf NBYTES,w
	movwf SEQCNT	
	clrf OLDCARRY ; azzera eventuale riporto di operazioni precedenti
	movlw h'01'
LoopCompl:
	movwf BYTEVL ; salva il secondo addendo
	clrf NEWCARRY ; inizializza riporto di operazioni successive
	comf INDF ; esegue il complemento a uno del byte corrente
 	addwf INDF ; somma nel registro il byte '1'
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo
	movf OLDCARRY,w 
	addwf INDF ; somma nel registro anche il Carry precedente
	btfsc STATUS,C ; se si genera un riporto
	incf NEWCARRY,f  ; incrementa NEWCARRY (per il byte successivo	 
	movf NEWCARRY,w
	movwf OLDCARRY ; adesso NEWCARRY diventa OLDCARRY
	decf FSR
	movlw h'00' ; byte a zero da sommare per il complemento a due
	decfsz SEQCNT,1
	goto LoopCompl
	return
;************************************************************
; SOTTR A N BYTES (xx-xx) - ((x-10)x-(x-10)x) = (xx-xx)
;************************************************************
SOTTR:
	movwf COMPLRF ; salva indirizzo sottraendo	
	call COMPL ; esegue il complemento a due del sottraendo
	movf COMPLRF,w ; recupera indirizzo sottraendo
	call SOMMA ; esegue la somma
	return
;*************************
; DELAY Routine (8 words)
;*************************
DELAY_STD:
	movlw h'FF'
DELAY:
	movwf DLCNT1
DlLp1:	
	movlw h'FF'
	movwf DLCNT2
DlLp2:	
	decfsz DLCNT2,1
	goto DlLp2
	decfsz DLCNT1,1
	goto DlLp1
	return
;******************************************
; EEREAD Routine: indirizzo in w
;******************************************
EEREAD:
	movwf EEADR ;Address to read
	bsf EECON1,RD ;EE Read
	movf EEDAT,W ;risultato in w
	return
;*************************************************************
; EEWRITE Routine: byte in EEDAT, indirizzo in EEADR  
;*************************************************************
EEWRITE:
	bsf EECON1,WREN ;Enable write
	movlw h'55' ;Unlock write
	movwf EECON2
	movlw h'AA'
	movwf EECON2
	bsf EECON1,WR ;Start the write
	movlw h'0A' ; 06 è il minimo
	call DELAY
	return
;*************************************************************
; USAGECOUNTER Routine: in EEPROM 00-03 il valore corrente 
;*************************************************************
USAGECOUNTER:
	bcf STATUS,RP0 ; Bank 0
	clrf 0x20
	clrf 0x21
	clrf 0x22
	movlw h'01'
	movwf 0x23
	movlw h'04'
	bsf STATUS,RP0 ; Bank 1	
	movwf NBYTES
	movlw h'23'
	call SOMMA
 ; Salva il nuovo valore di contatore in EEPROM
	movlw h'00'
	movwf EEADR
	movlw h'04'
	movwf SEQCNT
	movlw h'30' 
	call INTEE_WR
	return
;
;************************************************************
; START KEYS (S0 S1) 
;************************************************************
STARTKEYS:	
	bcf STATUS,RP0 ; Bank 0;s[0] = 'CB8196CA68D52AFC'
	movlw h'CB'
	movwf 0x20
	movlw h'81'
	movwf 0x21
	movlw h'96'
	movwf 0x22
	movlw h'CA'
	movwf 0x23
	movlw h'68'
	movwf 0x24
	movlw h'D5'
	movwf 0x25
	movlw h'2A'
	movwf 0x26
	movlw h'FC'
	movwf 0x27
;s[1] = '06F0886EC3C1ED6D'
	movlw h'06'
	movwf 0x28
	movlw h'F0'
	movwf 0x29
	movlw h'88'
	movwf 0x2A
	movlw h'6E'
	movwf 0x2B
	movlw h'C3'
	movwf 0x2C
	movlw h'C1'
	movwf 0x2D
	movlw h'ED'
	movwf 0x2E
	movlw h'6D'
	movwf 0x2F
	bsf STATUS,RP0 ; Bank 1
	return
;
; ************************************************
; ROUTINES DI TRASMISSIONE E GESTIONE
; ************************************************
;
;*******************************************
; BYTE_TX ROUTINE: byte da trasmettere in w 
;*******************************************
BYTE_TX:
	movwf BYTEVL
	movlw h'08'
	movwf BYTCNT ; inizializza il contatore di bit
TxLoop:
	bcf STATUS,RP0 ; Bank 0
	bsf PORTA,5; Trasmette livello logico alto
	bsf STATUS,RP0 ; Bank 1
	call BITDELAY
	bcf STATUS,RP0 ; Bank 0
	bcf PORTA,5; Trasmette livello logico basso
	bsf STATUS,RP0 ; Bank 1
	call BITDELAY	 
	rlf BYTEVL,1 ; Carry = MSB di BYTEVL
	btfss STATUS,0 ; se Carry=01 salta e invia un 1
	goto FineBit
; Invia un 1
	call BITDELAY ; invia un 1
	incf UNOCNT
FineBit:
	decfsz BYTCNT,1 
	goto TxLoop	; esamina il bit successivo di BYTEVL
	return
;
;***********************************************
;  BITDELAY: tempo di trasmissione
;***********************************************
BITDELAY:
	movlw h'60'
BDELAY:
	movwf DLCNT1
BDly1:
	decfsz DLCNT1,1
	goto BDly1
	return
;
;******************
; BUFFER_TX ROUTINE
;******************
BUFFER_TX:
	movwf FSR
	clrf UNOCNT ; azzera conteggio bit a 0
BufLoop:	
	movf INDF,w
	call BYTE_TX
	incf FSR
	decfsz SEQCNT,1
	goto BufLoop
	movf UNOCNT,w 
	call BYTE_TX ; invio byte UNOCNT
	return
;
;********************************************************************************
; AB_RECOV: 
;********************************************************************************
;
AB_RECOV:
	movlw h'04' ; indirizzo del flag di programmazione in EEPROM
	call EEREAD ; legge da EEPROM in w
	btfsc STATUS,2 ; salta se Z=0 cioè se il flag NON è =h'00'
	goto NormRecov ; Z=1: flag è =h'00' ; contatore già inizializzato
;
; flag<>h'00': Inizializzazione contatore 
;
	call KEY_LOAD_IN
	clrf EEDAT ; mette flag = h'00'
	movlw h'04'
	movwf EEADR
	call EEWRITE ; condizione di contatore inizializzato
	goto EndRecov
NormRecov:
	movlw h'00'
	movwf EEADR
	movlw h'04'
	movwf SEQCNT	
	movlw h'30'	
	call INTEE_RD 	
	call KEY_LOAD
EndRecov:
	call USAGECOUNTER
	return
;********************************************************************************
; INTEE_WR ROUTINE da RAM a EEPROM, lunghezza sequenza in SEQCNT 
;********************************************************************************
INTEE_WR:
	movwf FSR
IntEEWrLoop:
	movf INDF,w
	movwf EEDAT
	call EEWRITE
	incf FSR
	incf EEADR
	decfsz SEQCNT,1
	goto IntEEWrLoop
	return
;********************************************************************************
; INTEE_RD ROUTINE da EEPROM a RAM, lunghezza sequenza in SEQCNT 
;********************************************************************************
INTEE_RD:
	movwf FSR
IntEERdLoop:
	bsf EECON1,RD ;EE Read
	movf EEDAT,W ;risultato in w	
	movwf INDF
	incf FSR
	incf EEADR
	decfsz SEQCNT,1
	goto IntEERdLoop
	return
;
;************************************************
;KEY_LOAD: carica in 30-3F la stringa da inviare
;************************************************
KEY_LOAD_IN:		
	bcf STATUS,RP0 ; Bank 0
; Contatore = '00000001'
	movlw h'00'
	movwf 0x30
	movlw h'00'
	movwf 0x31
	movlw h'00'
	movwf 0x32
	movlw h'01'
	movwf 0x33
KEY_LOAD:
	bcf STATUS,RP0 ; Bank 0
; LockId = '445566778899AABBCCDDEE'
	movlw h'44'
	movwf 0x34
	movlw h'55'
	movwf 0x35
	movlw h'66'
	movwf 0x36
	movlw h'77'
	movwf 0x37
	movlw h'88'
	movwf 0x38
	movlw h'99'
	movwf 0x39
	movlw h'AA'
	movwf 0x3A
	movlw h'BB'
	movwf 0x3B
	movlw h'CC'
	movwf 0x3C
	movlw h'DD'
	movwf 0x3D
	movlw h'EE'
	movwf 0x3E
; KeyId = '04'
	movlw h'04'
	movwf 0x3F
	bsf STATUS,RP0 ; Bank 1	
	return
;******************************************************************************
	end ; directive 'end of program'
;******************************************************************************