PICman
Joined: 02 Nov 2007 Posts: 26
|
| ...Line-by-line software access to I2C |
Posted: Wed Mar 25, 2009 5:02 am |
|
|
This code is a "do-nothing" code that shows how I2C works. It continuously writes data into a 24LC256 I2C serial EEPROM and then checks it's contents for data integrity. Comments are sent on RB2 in 9600,n,8,1 (TTL)
The data is generated by a LFSR PRBG so it is random looking.
It's main goal is to show the user how I2C works and to implement I2C in microcontrollers that do not have I2C implemented.
| Code: |
//
// My first experiences with I2C: EEPPROMS.
//
// I didn't want with the tiny 24LC00 and many
// electronics stores hold the 24LC256. So i
// chose it. The 24LC256 holds 262144 bits of
// data organized in a 32kB fashion (32768 * 8)
//
// This firmware includes random R/W procedures
// for the 24LC256 I2C serial EEPROM.
//
// This firmware is aimed at PIC's that do
// not include the integrated I2C protocol. It's
// goal is also to explain you how I2C works.
//
// _________ _________
// __| \/ |__
// Ground |__|A0 Vdd|__| +5V
// __| __ |__
// Ground |__|A1 EEPROM WE |__| Ground to write, +5V to protect.
// __| 24LC256 |__
// Ground |__|A2 SCL|__|Serial CLock
// __| |__
// Ground |__|Vss SDA|__|Serial DAta
// |____________________|
//
// I2C lines:
// ==========
//
// What is interesting with I2C (developed by
// Philips), is that only two lines are required to access
// I2C devices. Those two lines are: SDA (Serial DAta) et SCL
// (Serial CLock).
//
// Another important feature of I2C is that ALL I2C devices
// can ONLY pull the lines LOW (to ground). Never, an I2C
// device may pull HIGH a line. Pulling-up the SDA and SCL
// lines is done by two pull-up RESISTORS (one per line).
// The suggested value for pullup resistors is 4700-20k ohms.
//
// Waveforms:
// ==========
//
// In the I2C protocol, normal address/read/write on the SDA
// line is done ONLY when the SCL line is LOW.
//
// The ONLY times when SDA is transited while SCL is high is
// on the (S)tart and sto(P) commands.
//
////////////////////////////////////////////////
// ____S(tart) // (sto)P___ //
// SDA \_______ // ___________/ SDA //
// _________ // _________ //
// SCL \__ // _____/ SCL //
// // //
////////////////////////////////////////////////
// ___ ___ ___ ___ ___ ___ ___ ___ ___
// SCL _/ 1 \___/ 0 \___/ 1 \___/ 0 \___/ A2\___/ A1\___/ A0\___/r/w\__/ack\
// _______ _______
// Mas_/ \_______/ \_______________________________________
//
// Sla \_____/
//
// For EEPROMS, 4 first bits MUST BE set at 1010.
// Every other value will be adressed to another
// component and will be ignored by EEPROMS.
//
//
// Bits A2, A1 and A0 on the stream must correlate with the hardwired
// logic states of corresponding pins (reapectively, pins 3, 2 and 1)
// of the I.C.
//
// Every other combination will be ignored by the EEPROM. This
// feature allows the user to use several (up to eight) 24LC256's
// on the same I2C pair by using different hardwired combinations on
// pins A2-0.
//
// For now, all A0-2 pins are tied to ground (Vss).sont à ground avec Vss.
//
// PIC16F648A
//
// RB1 = RXD
// RB2 = TXD
//
// _________ _________
// __| \/ |__
// |__|Ra2 Ra1|__|SDA
// __| |__
// |__|Ra3 Ra0|__|SCL
// __| |__
// |__|Ra4 clkin|__|
// __|____ |__
// +5V|__|MCLR/Vpp clkout|__|
// __| |__
// 0V|__|Vss Vdd|__| +5V
// __| |__
// |__|Rb0/int Rb7/ICSPDAT|__|
// __| |__
// |__|Rb1 Rb6/PGC|__|
// __| |__
// 9600baud |__|Rb2 Rb5|__|
// __| |__
// |__|Rb3 Rb4|__|
// |____________________|
//
#include <16F648A.h>
//#FUSES XT,NOWDT,PUT,NOPROTECT,BROWNOUT,NOMCLR,NOLVP,NOCPD
//#use fast_io(b) // We DO want to work around with TRIS (I2C port)
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=pin_b2,rcv=pin_b1,bits=8)
#FUSES intrc,NOWDT,PUT,NOPROTECT,BROWNOUT,NOMCLR,NOLVP,NOCPD
//no master clear a5 (reset) ;cpd barrer eedata;nolvp lo-volt prog
////////////////////////////
void rad(void); //
void init_pic(void); //
int8 i2c_read(void); //
void i2c_write(int8); //
void S(void); //
void P(void); // P R O T O T Y P E S
void envoi_donnees(int1); //
void envoi_octet(int8); //
int1 lire_donnees(void); //
void aff_err(int8); //
int8 adresse_haute; //
int8 adresse_basse; //
int8 donnee; //
int8 hasard; //
int8 x0,x1,x2,x3,x4,x5; //
int8 x6,x7,y; //
////////////////////////////
//#ZERO_RAM
//#int_RTCC
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
void main() /////
{ /////
int8 donnee,compteur,compteur2; /////
int1 valide; /////
int16 nbre_erreurs,nbre_prog,octets_ecrits; /////
/*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*/ /////
init_pic(); /////
adresse_haute=0x00; // Adresse dans un 24LC256: 0x0000-0x07FF /////
adresse_basse=0x00; // Adresse basse = 0-255 haute=0-127 /////
////////////// /////
x0=174; // Initialisation /////
x1=152; // RAD /////
x2=67; // /////
x3=223; // Here, i initialise an LFSR (Linear Feedback Shift /////
x4=98; // Register) to be able to always generate the same /////
x5=42; // pseudo-random stream. This way, i will be able, later, /////
x6=135; // to re-initialise the LFSR the same way to start the /////
x7=201; // verify routine with the same data. /////
////////////// /////
for(compteur=0;compteur<3;compteur++) /////
printf("\n\r----------Writing I2C EEPROM-------------------"); /////
/////
/////
printf("\n\r"); /////
/////
compteur2=0; /////
nbre_prog=0; /////
octets_ecrits=0; /////
valide=1; /////
while(valide) /////
{ /////
rad(); /////
////////////////////////////////////////////// /////
donnee=i2c_read(); // Pre-read. If the correct /////
if(donnee==hasard) // data is already present /////
compteur2++; // in the EEPROM, i don't /////
else // touch it. This procedure /////
{ // has two advantages: /////
printf("\n\rAdr: %2X%2X: ", // /////
adresse_haute,adresse_basse); // /////
printf(" ecrit: %2X",hasard); // /////
i2c_write(hasard); // 1) Much faster /////
// /////
donnee=i2c_read(); // 2) No useless /////
printf(" Lu: %2X",donnee); // writes on /////
if(donnee==hasard) // write-limited EEPROM /////
octets_ecrits++; // cells. /////
} // /////
if(donnee==hasard) // /////
nbre_prog++; // /////
else // /////
aff_err(13); // /////
////////////////////////////////////////////// /////
/////
//////////////////////////////////////////// /////
if(adresse_basse==255) // /////
{ // /////
if(adresse_haute==127) // Address counter /////
valide=0; // Generates valid addresses /////
} // between 0x0000 and 0x7FFF /////
adresse_basse++; // (24LC256) /////
if(adresse_basse==0) // /////
adresse_haute++; // /////
//////////////////////////////////////////// /////
/////
//////////////////////////////////////////// /////
if(compteur2==0) // At each 256 correct /////
printf("."); // verifications /////
//////////////////////////////////////////// /////
} /////
printf("\n\r%lu=bytes written during this session",octets_ecrits); /////
printf("\n\r%lu=Total of good bytes:",nbre_prog); /////
/////////////////////////////////////////////////////////////////////////////
while(1) /////
{ /////
printf("\n\r--------Verification of I2C EEPROM-------------"); /////
printf("\n\r"); /////
nbre_erreurs=0; /////
adresse_haute=0x00; /////
adresse_basse=0x00; /////
////////////// LFSR Initialisation /////
x0=174; // /////
x1=152; // Here, i initialise the LFSR the same way as i did on /////
x2=67; // beginning. This way, the LFSR will generate the EXACT /////
x3=223; // same pseudorandom stream for verification as it did on /////
x4=98; // writing. This way, i can fill the EEPROM with random /////
x5=42; // looking data then, i can test it's data integrity. /////
x6=135; // /////
x7=201; // /////
////////////// /////
/////
///////////////////////////////////////////// /////
valide=1; // Verification of EEPROM's /////
while(valide) // data contents. /////
{ // /////
rad(); // /////
donnee=i2c_read(); // /////
if(donnee!=hasard) // /////
{ // /////
printf(" %X%X",adresse_haute, // /////
adresse_basse); // /////
nbre_erreurs++; // /////
} // /////
///////////////////////////////////////////// /////
/////
///////////////////////////////////////////// /////
// /////
if(adresse_basse==255) // /////
{ // /////
printf("+"); // /////
if(adresse_haute==127) // Address counter /////
valide=0; // /////
} // /////
adresse_basse++; // /////
if(adresse_basse==0) // /////
adresse_haute++; // /////
// /////
} // /////
printf("\n\rTotal: %lu error(s)", // /////
nbre_erreurs); // /////
///////////////////////////////////////////// /////
} /////
} /////
/////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
void init_pic(void) //
{ //
output_a(0); // IT IS IMPORTANT to set both bits 0 //
// and 1 to LOW and MAINTAIN them LOW //
// throughout the whole program ! //
// REMEMBER ! an I2C device CAN NOT //
// pull high an I2C line , master or //
// slave ! //
output_b(0); //
set_tris_a(0b11111111); // gauche=bit7, droite=bit0 //
set_tris_b(0b11111011); // gauche=bit7, droite=bit0 //
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256); //
setup_timer_1(T1_DISABLED); // PIC
setup_timer_2(T2_DISABLED,0,1); // initialisation
setup_comparator(NC_NC_NC_NC); //not connected // Routine.
setup_vref(FALSE); // not used //
disable_interrupts(INT_RTCC); //
disable_interrupts(GLOBAL); //
// setup_oscillator(False); //
port_b_pullups(true); //
} //
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int8 i2c_read()
/////////////////////////////////////////////////////////////////////
{ //
int1 ack,ein; //
int8 rot; //
int8 compteur; //
/*=-=*//*=-=*/ //
//
//
/////////// //
S(); // Start //
/////////// //
// I2C serial
//////////////////////// // EEPROM
envoi_octet(0xA0); // ADRESSAGE/ÉCRITURE // reading
//////////////////////// //
//
////////////////////////////////// //
envoi_octet(adresse_haute); // Send //
////////////////////////////////// correct //
envoi_octet(adresse_basse); // address to //
////////////////////////////////// EEPROM. //
//
/////////// Pour la lecture du EEPROM. on doit //
S(); // exécuter un second "Start" après //
/////////// l'adressage... //
//
//////////////////////// ...et on envoie //
envoi_octet(0xA1); // une commande de // I2C serial
//////////////////////// lecture // EEPROM
// reading
////////////////////////////////// //
donnee=0; // I2C EEPROM reading routine by //
// itself. //
compteur=7; // //
while(!bit_test(compteur,7)) // For tha, the "rot" variable is //
{ // used. "rot"'s bit 0 is loaded //
#asm // with the read bit on the I2C's //
rlf rot,f // SDA line. //
#endasm // //
ein=lire_donnees(); // Bertween each bit loading, the //
// "rot" variable is rotated left. //
bit_clear(rot,0); // //
if(ein) // After eight, the "rot" variable //
bit_set(rot,0); // is loaded with the full //
compteur--; // EEPROM's byte, the MSB loaded //
} // first. //
////////////////////////////////// //
//
////////////////////////// Final ACK //
ack=lire_donnees(); // //
if(ack==0) // Here, at the end of byte read, the //
aff_err(11); // slave EEPROM MUST NOT send an ACK. //
////////////////////////// //
//
/////////// //
P(); // stoP //
/////////// //
//
return(rot); //
} //
//////////////////////////////////////////////////////////
void i2c_write(int8 octet)
/////////////////////////////////////////////////
{ //
int1 ack,valide; //
int8 limite_ecriture; //
/*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*/ //
/////////// //
S(); // Start //
/////////// //
//
//////////////////////// //
envoi_octet(0xA0); // ADRESSING/WRITING //
//////////////////////// //
//
////////////////////////////////// //
envoi_octet(adresse_haute); // Send //
////////////////////////////////// correct //
envoi_octet(adresse_basse); // address to //
////////////////////////////////// EEPROM. //
//
///////////////////////// Send byte to be //
envoi_octet(octet); // written into the //
///////////////////////// EEPROM. //
//
/////////// At this stoP, EEPROM writes //
P(); // the byte in it's internal memory //
/////////// cells. // Écriture du
// EEPRM I2C
//////////////////////////// //
limite_ecriture=0; // //
valide=0; // Here, we send a //
while(valide==0) // check byte to the //
{ // EEPROM. It will //
/////////// // reply with an ACK //
S(); // Start // only when the //
/////////// // writing procedure //
envoi_donnees(1); // is completed. //
envoi_donnees(0); // //
envoi_donnees(1); // //
envoi_donnees(0); // //
envoi_donnees(0); // //
envoi_donnees(0); // //
envoi_donnees(0); // //
envoi_donnees(0); // //
// //
ack=lire_donnees(); // //
if(ack==0) /////// //
valide=1; // //
if(limite_ecriture>253) // //
{ // //
aff_err(12); /////// //
valide=1; // //
} // //
/////////// // //
P(); // stoP // //
/////////// // //
limite_ecriture++; // //
} // //
//////////////////////////// //
} //
/////////////////////////////
/////////////////////////////////////////////////////////
void S(void) //
{ //
int1 valide; //
int8 essais; //
/*=-=*//*=-=*//*=-=*//*=-=*/ //
set_tris_a(0b11111111); // Eneryone up ! //
// //
// Throughout this //
// program, TRIS is used //
// to either pull down a //
// line or RELEASE it to //
// high (via the pullup //
// resistors). //
// //
// Bits 0 (SCL) and 1 (SDA) //
// are either RESET LOW to //
// pull down or SET HIGH to //
// release the //
// corresponding line. //
delay_us(4); //
//////////////////////////////////////////// We check //
if(!input_state(40)||!input_state(41)) // that BOTH //
aff_err(7); // SDA and //
//////////////////////////////////////////// SCL=High //
//
////////////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // //
{ // SDA is pulled // Start
set_tris_a(0b11111101); // down. // routine.
delay_us(4); // //
if(!input_state(41)) // //
valide=1; // SDA is tested //
else // to be sure it's //
{ // LO. //
aff_err(0); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
////////////////////////////////////// //
//
////////////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // // Start
{ // Then, SCL is // routine.
set_tris_a(0b11111100); // pulled down. //
delay_us(4); // //
// //
if(!input_state(40)) // And we check //
valide=1; // that SCL is //
else // LOW. //
{ // //
aff_err(1); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
delay_us(4); // //
////////////////////////////////////// //
} //
/////////////////////////////////////////////////////////
////////////////////////////////////////////////////
void P(void) //
{ //
int1 valide=0; //
int8 essais; //
/*=-=*//*=-=*//*=-=*//*=-=*//*=-=*/ //
///////////////////////////// Before releasing //
set_tris_a(0b11111100); // SCL, we must get //
delay_us(4); // sure that SDA is //
///////////////////////////// LOW. //
//
//////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // //
{ // We release SCL //
set_tris_a(0b11111101); // high... // stoP
delay_us(4); // // routine
// //
if(input_state(40)) // SCL is verified //
valide=1; // for it's //
else // "highness" ! //
{ // //
aff_err(1); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
//////////////////////////////// //
delay_us(4); //
//
//////////////////////////////// //
essais=0; // //
valide=0; // THEN, SDA is //
while(valide==0) // released high. //
{ // //
set_tris_a(0b11111111); // // stoP
delay_us(4); // // routine
// //
if(input_state(41)) // SDA is //
valide=1; // tested //
else // high. //
{ // //
aff_err(10); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
//////////////////////////////// //
} //
////////////////////////////////////
///////////////////////////////////////////////////////////
void envoi_octet(int8 rot) //
////////////////////////////////// //
{ // The "to-be-sent" byte // PIC-to-I2C EEPROM
int1 ein,ack; // is transferred to the // byte sending routine.
int8 compteur; // "rot" variable. //
/*=-=*//*=-=*//*=-=*//*=-=*/ // //
compteur=7; // //
while(!bit_test(compteur,7)) // From "rot", we send //
{ // the MSB (bit 7) bit //
ein=0; // to I2C. //
if(rot&0x80) // //
ein=1; // Then, "rot" is //
envoi_donnees(ein); // rotated left to pass //
#asm // to the next bit. //
rlf rot,f // //
bcf rot,0 // This way, all eight //
#endasm // bits are sent to I2C, //
compteur--; // one at a time, //
} // starting with //
////////////////////////////////// the heaviest one. //
//
///////////////////////// At the end of each byte, the //
ack=lire_donnees(); // PIC master waits for an //
if(ack==1) // ACKnowledge from the slave //
aff_err(6); // EEPROM. To send it's ACK, the //
///////////////////////// slave PULLS DOWN SDA. The //
// master releases it's SDA line and checks that the SDA //
// line is HELD DOWN by the slave. //
} //
///////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////
void envoi_donnees(int1 donnee) //
{ //
int1 valide=0; //
int8 essais; //
/*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*//*=-=*/ //
//////////////////////////////// //
essais=0; // //
while(valide==0) // //
{ // SCL is pulled down //
set_tris_a(0b11111110); // while SDA is left free to go //
delay_us(4); // high. //
//////////////////////////////// //
//
///////////////////////////// Master checks that SDA goes HI. // Bit sending
if(!input_state(41)) // If SDA id held LOW, then the // procedure
aff_err(11); // slave EEPROM has sent an // on I2C port.
// unattended ACK. //
// //
///////////////////////////// //
//
//////////////////////////////////// //
if(donnee==1) // SDA is either held LOW //
set_tris_a(0b11111110); // or released HIGH. //
else // obeying to the data bit. //
set_tris_a(0b11111100); // //
// //
// //
delay_us(4); // //
//////////////////////////////////// //
//
//////////////////////////////// //
if(donnee) // //
{ // //
if(input_state(41)) // Verification. Has the SDA //
valide=1; // line followed the DATA bit ? //
else // //
{ // //
aff_err(2); // //
essais++; // //
if(essais>7) // //
valide=1; // // Bit sending
} // // procedure
} // // on I2C port.
else // //
{ // //
if(!input_state(41)) // //
valide=1; // //
else // //
{ // //
aff_err(3); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
// //
} // //
//////////////////////////////// //
//
//////////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // //
{ // //
if(donnee) // //
set_tris_a(0b11111111); // // Bit sending
else // SCL is released HIGH... // procedure
set_tris_a(0b11111101); // // on I2C port.
// //
delay_us(4); // //
// //
if(input_state(40)) // Is SCL HIGH ? //
valide=1; // //
else // //
{ // //
aff_err(4); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
//////////////////////////////////// //
//
/////////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // //
{ // //
if(donnee) // ...and SCL is pulled //
set_tris_a(0b11111110); // down. // Bit sending
else // // procedure
set_tris_a(0b11111100); // // on I2C port.
// //
delay_us(4); // //
// //
if(!input_state(40)) // ...and checked LOW. //
valide=1; // //
else // //
{ // //
aff_err(3); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
// //
/////////////////////////// //
delay_us(4); //
} //
//////////////////////////////////////////////////
////////////////////////////////////////////////////////////
int1 lire_donnees(void) //
{ //
int1 lecture; //
int1 valide=0; //
int8 essais; //
/*=-=*//*=-=*//*=-=*//*=-=*//*=-=*/ // Bit reading
//////////////////////////////// // procedure
set_tris_a(0b11111110); // SDA is left high... // on I2C port.
delay_us(4); // //
//////////////////////////////// //
//
//////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // //
{ // ...and SCL is left HIGH. //
set_tris_a(0b11111111); // // Réception
// // d'un
delay_us(4); // delay // bit sur
// // le port
if(input_state(40)) // We check that SCL is // I2C
valide=1; // high. //
else // //
{ // //
aff_err(5); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
//////////////////////////////// //
//
///////////////////////// //
lecture=0; // //
if(input_state(41)) // SDA line is read... //
lecture=1; // //
// ...and saved on "lecture" //
delay_us(4); // boolean. //
///////////////////////// //
//
//////////////////////////////// //
essais=0; // //
valide=0; // //
while(valide==0) // ...and SCL is pulled //
{ // DOWN. //
set_tris_a(0b11111110); // //
// //
delay_us(4); // //
// //
if(!input_state(40)) // and checked LOW. //
valide=1; // //
else // //
{ // //
aff_err(5); // //
essais++; // //
if(essais>7) // //
valide=1; // //
} // //
} // //
//////////////////////////////// //
delay_us(4); //
return(lecture); //
} //
//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void aff_err(int8 erreur) //
{ //
if(erreur!=13) //
printf("\n\rError # %u: ",erreur); //
if(erreur==0) //
printf("SDA not down in (S)tart"); //
if(erreur==1) //
printf("SCL not down in (S)tart or not UP is sto(P)"); //
if(erreur==2) //
printf("SDA not following DATA HIGH in sending to EEPROM"); //
if(erreur==3) //
printf("SDA not following DATA LOW in sending to EEPROM"); //
if(erreur==4) //
printf("SCL not rising high when data sent to EEPROM"); //
if(erreur==5) //
printf("SCL not following on data reading/ACK of EEPROM"); //
if(erreur==6) //
printf("NAK!"); //
if(erreur==7) //
printf("SCL and SDA lines not HI before (S)tart"); //
if(erreur==8) //
printf("SCL line not HI after sto(P)"); //
if(erreur==9) //
printf("SDA line not HI after sto(P)"); //
if(erreur==10) //
printf("SDA not going HI during sto(P)"); //
if(erreur==11) // Error messages
printf("Unattended ACK !!"); //
if(erreur==12) //
printf("Writing time limit exceeded"); //
if(erreur==13) //
printf(" Data not written (WP ?)"); //
delay_ms(100); //
} //
////////////////////////////////////////////////////////////
////////////////////////////////////
void rad(void) //
{ //
int8 c2; //
//
#asm //
//
movlw 8 // Eight times to //
movwf c2 // obtain a byte //
//
boucle2: //
// LFSR used
bsf y,0 // ODD // to generate
// pseudo-random
btfsc x0,5 // Multi-input XOR // data.
incf y // gate. (INCF acts //
btfsc x1,6 // as a XOR on "y" //
incf y // bit 0) //
btfsc x2,4 // //
incf y // //
btfsc x3,7 // //
incf y // //
btfsc x4,2 // //
incf y // //
btfsc x5,3 // //
incf y // //
btfsc x6,4 // //
incf y // //
btfsc x7,7 // //
incf y // //
// //
// //
//
//
rlf x0,f // LEFT rotate // LFSR
rlf x1,f // //
rlf x2,f // //
rlf x3,f // //
rlf x4,f // //
rlf x5,f // //
rlf x6,f // //
rlf x7,f // //
//
bsf x0,0 // Access to //
btfss y,0 // bit 0 of LFSR //
bcf x0,0 // after bit //
// rotate //
//
decfsz c2,f //
goto boucle2 //
//
movf x0,w //
movwf hasard //
#endasm //
return; //
//
} //
////////////////////////////////////
|
|
|