Created
June 9, 2011 13:04
-
-
Save monsonite/1016689 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// File Name : Nanode_MAC.c | |
// UNIO_memory , ATmega family , C language , bit-bang method. | |
// Dependencies : | |
// Processor : ATmega328 | |
// Hardware : Nanode 5 | |
// Debug Module : | |
// I.D.E. : Arduino | |
// Company : Arbour Wood Ltd | |
// Author : Ken Boak | |
// Rough and ready translation from MSP430 code May 22 2011 | |
#include <avr/io.h> //This is our usual include | |
#define DEVADR 0xa0 // slave address | |
#define START 0x55 // start header | |
#define READ 0x03 // READ instruction | |
#define CRRD 0x06 // READ from crt address instruction | |
#define WRITE 0x6c // WRITE instruction | |
#define WREN 0x96 // WRITE ENABLE instruction | |
#define WRDI 0x91 // WRITE DISABLE instruction | |
#define RDSR 0x05 // READ STATUS register instruction | |
#define WRSR 0x6e // WRITE STATUS REGISTER instruction | |
#define ERAL 0x6d // ERASE entire array instruction | |
#define SETAL 0x67 // SET entire array instruction | |
#define NOPROT 0x00 // disable all write protections | |
#define SCIO 0x01 // SCIO = PORTD,7 | |
#define STRSZ 0x10 // size of string = 16 bytes | |
#define timeout_bastard 0x14 // timeout_bastard at sampling SAK/NOSAK | |
#define PD7 PORTD7 | |
#define QBT 0xa0 // quarter bit(timer) --> 12 Khz | |
#define QBI 0x20 // quarter bit(instr) (32:2us)=16us MAX | |
unsigned char err_cnt ; // error counter | |
unsigned char eep_buf ; // eeprom's data buffer | |
unsigned int tqb ; // calculated externally and loaded in | |
// timer_A as quarter bit | |
unsigned int thb ; // calculated externally and loaded in | |
// timer_A as half bit | |
unsigned int iqb ; // quarter bit through instructions | |
unsigned int ihb ; // half bit through instructions | |
unsigned char load[STRSZ] ; // global string for "copystr" function | |
unsigned int LED_6; | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// FUNCTIONS PROTOTYPES | |
//.............................................................................. | |
void ini_wdt(void); | |
void ini_rosc(void); | |
void ini_gpio(void); | |
void ini_tim(void); | |
void mak(void); | |
void nomak(void); | |
void sak(void); | |
void sakq(void); | |
void nosak(void); | |
void uni_wr(void); | |
unsigned char uni_rdq(void); | |
void uni_wrmns(void); | |
void uni_wrms(unsigned char ms); | |
void uni_wrnms(unsigned char nms); | |
void uni_head(void) ; | |
void uni_head2(void) ; | |
void uni_cmnd(unsigned char cmnd) ; | |
void uni_cmnd2(unsigned char cmnd) ; | |
void uni_eral(void); | |
void uni_setal(void); | |
void uni_setal2(void); | |
void uni_wrsr(unsigned char stat) ; | |
void ini_unio(void) ; | |
void uni_wippol(void); | |
unsigned char uni_rdsr(void) ; | |
void uni_wrbyte(unsigned int eep_adr,unsigned char eep_data); | |
void uni_rdbyte(unsigned int eep_adr,unsigned char *dst); | |
void uni_crrdbyte(unsigned char *dst); | |
void uni_wrstr(unsigned char *source,unsigned int eep_adr,unsigned char lofsstr); | |
void uni_rdstr(unsigned char *dest,unsigned int eep_adr,unsigned char lofdstr); | |
void uni_crrdstr(unsigned char *dest,unsigned char lofdstr); | |
void dltim(unsigned int steps); void dlins(unsigned int steps); | |
void calcdly(void); | |
void dlthb(void); | |
void dltqb(void); | |
void dlihb(void); | |
void dliqb(void); | |
void dlythdr(void); | |
void dlytss(void); | |
void dlystby(void); | |
void dly5ms(void); | |
void dly250ms(void); | |
void dly1s(void); | |
void final_error(void); | |
void copystr(unsigned char d[],unsigned char s[],unsigned char strz); | |
void setup(){ | |
DDRD = DDRD | B11111100; // Sets pins 2 to 7 as outputs | |
pinMode(6,OUTPUT); | |
PORTD |= (1<<PD7) ; // PORTD. 7 = 1 | |
// dlihb() ; // dly halfbit through instructions | |
PORTD &= ~(1<<PD7) ; // PORTD. 7 = 0 | |
// dlihb() ; // dly halfbit through instructions | |
PORTD |= (1<<PD7) ; // PORTD. 7 = 1 | |
// dlihb() ; // dly halfbit through instructions | |
PORTD &= ~(1<<PD7) ; // PORTD. 7 = 0 | |
dlihb() ; // dly halfbit through instructions | |
PORTD |= (1<<PD7) ; // PORTD. 7 = 1 | |
dlihb() ; // dly halfbit through instructions | |
PORTD &= ~(1<<PD7) ; // PORTD. 7 = 0 | |
// dlihb() ; // dly halfbit through instructions | |
// digitalWrite(6,HIGH); | |
// dly250ms(); | |
// digitalWrite(6,LOW); | |
// dly250ms(); | |
// digitalWrite(6,HIGH); | |
// dly250ms(); | |
// digitalWrite(6,LOW); | |
} // End of setup() | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// INITIALIZATION FUNCTIONS | |
//.............................................................................. | |
// ¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// UNIO CONTROL FUNCTIONS | |
//........................................................................ | |
void mak(void){ | |
PORTD &= ~(1<<PD7); // PORTD. 7 = 0 | |
dlihb(); // dly halfbit through instructions | |
PORTD |= (1<<PD7) ; // PORTD. 7 = 1 | |
dlihb(); // dly halfbit through instructions | |
} | |
//........................................................................ | |
void nomak(void) | |
{ PORTD |= (1<<PD7) ; // PORTD. 7 = 1 | |
// dlthb() ; // dly halfbit through timer | |
dlihb() ; // dly halfbit through instructions | |
PORTD &= ~(1<<PD7) ; // PORTD. 7 = 0 | |
// dlthb() ; // dly halfbit through timer | |
dlihb() ; // dly halfbit through instructions | |
} | |
//......................................................................... | |
void sak(void) // SAK = 0 - 1 | |
{ unsigned char wait=timeout_bastard ; // init "wait" variable | |
PORTD ^= (1 << PD7) ; // PORTD. 7 = 1 | |
DDRD &= ~(1<<PD7); PORTD |= (1<<PD7) ; // PORTD,7 = INPUT | |
while (PIND & (1<<PD7)) // if SCIO = 1 | |
{ wait-- ; // decrement timeout_bastard variable | |
if(wait==0){final_error() ;} } // if timeout_bastard , final error | |
// dlthb() ; dlthb() ; // wait a bit period | |
dlihb() ; dlihb() ; // wait a bit period | |
if(!(PIND & (1<<PD7))) // no edge inside SAK | |
{ final_error() ; } // same error inside SAK | |
else | |
{ PORTD ^= (1 << PD7) ; // set PORTD,7 | |
DDRD |= (1<<PD7); ; } } // if no_error, PORTD,7=OUTPUT | |
//......................................................................... | |
void sakq(void) // sample : 1/4 bit + 3/4 bit(QB) | |
{ | |
//PORTD ^= (1 << PD7) // PORTD. 7 = 1 | |
DDRD &= ~(1<<PD7); PORTD |= (1<<PD7) ; // PORTD,7 = INPUT | |
// dltqb() ; // wait quarter bit | |
dliqb() ; // wait quarter bit | |
if(PIND & (1<<PD7)){final_error();} // pin=1 at (1/4) bit, error | |
else { | |
// dlthb() ; // wait half bit till 3/4 bit | |
dlihb() ; // wait half bit till 3/4 bit | |
if(!(PIND & (1<<PD7))) // if pin=0 at (3/4) bit | |
{ final_error() ; } // error | |
else { | |
// dltqb() ; // wait till the end of bit | |
dliqb() ; // wait till the end of bit | |
DDRD |= (1<<PD7) ; } // restore pin as OUTPUT | |
} } | |
//......................................................................... | |
void nosak(void) | |
{ unsigned char wait=timeout_bastard ; // init wait variable | |
// PORTD ^= (1 << PD7) ; // PORTD. 7 = 1 | |
DDRD &= ~(1<<PD7); PORTD |= (1<<PD7) ; // PORTD,7 = INPUT | |
while(!(PIND & (1<<PD7))) // wait pin=1 | |
{ wait-- ; | |
if(wait==0){final_error(); } } // timeout_bastard, same errror as in SAK | |
// dlthb() ; dlthb() ; // wait end of bit | |
dlihb() ; dlihb() ; // wait end of bit | |
DDRD |= (1<<PD7) ; } // restore pin as OUTPUT | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// SERIALIZATION FUNCTIONS | |
//......................................................................... | |
void uni_wr(void) // writes an 8b streaming | |
{ unsigned char bitmask = 0x80 ; // bit mask for the char | |
while(bitmask) // for 8 bits | |
{ if(eep_buf&bitmask) // if ( bit=1) | |
{ PORTD &= ~(1<<PD7) ; // bit=1 --> 0-1 | |
// dlthb() ; // pin=0 + hfbit delay | |
dlihb() ; // pin=0 + hfbit delay | |
PORTD |= (1<<PD7) ; // pin=1 | |
dlthb() ; // pin=1 + hfbit delay | |
dlihb() ; // pin=1 + hfbit delay | |
} | |
else | |
{ PORTD |= (1<<PD7) ; // bit=0 --> 1-0 | |
// dlthb() ; // pin=1 + hfbit delay | |
dlihb() ; // pin=1 + hfbit delay | |
PORTD &= ~(1<<PD7) ; // pin=0 | |
// dlthb() ; // pin=0 + hfbit delay | |
dlihb() ; // pin=0 + hfbit delay | |
} | |
bitmask = bitmask >>1 ; } } // shift right mask for 8 bits | |
//.......................................................................... | |
unsigned char uni_rdq(void) // reads an 8b streaming | |
{ unsigned char bitmask = 0x80 ; // bit mask for the char | |
// P3OUT |=SCIO ; // PORTD. 7 = 1 | |
DDRD &= ~(1<<PD7); PORTD |= (1<<PD7) ; // SCIO = input | |
while(bitmask) // for 8 bits | |
{ | |
// dltqb() ; // first smpl = (1/4) bit | |
dliqb() ; // first smpl = (1/4) bit | |
if(!(PIND & (1<<PD7))) // if first sample=0 | |
{ | |
// dlthb() ; // wait a half bit period | |
dlihb() ; // wait a half bit period | |
if(!(PIND & (1<<PD7))) { final_error() ; } // if 2nd smpl=0, 0&&0->error | |
else { eep_buf|=bitmask ; } } // 0 && 1 => 1 | |
else | |
{ // if first smpl=1 | |
// dlthb() ; // wait a half bit period | |
dlihb() ; // wait a half bit period | |
if(PIND & (1<<PD7)) { final_error() ; } // if 2nd smpl=1,1&&1->error | |
else { eep_buf &= ~bitmask ; } } // 1 && 0 => 0 | |
// dltqb() ; | |
dliqb() ; // final quarter bit delay | |
bitmask = bitmask >>1 ; } // shift right mask for 8 bits | |
DDRD |= (1<<PD7) ; return eep_buf ; } // pin = out , return data buffer | |
//.............................................................................. | |
unsigned char uni_rd3q(void) // reads an 8b streaming | |
{ unsigned char bitmask = 0x80 ; // bit mask for the char | |
// P3OUT |=SCIO ; // PORTD. 7 = 1 | |
DDRD &= ~(1<<PD7); PORTD |= (1<<PD7) ; // SCIO = input | |
while(bitmask) // for 8 bits | |
{ | |
// dltqb() ; // delay (1/4) bit | |
dliqb() ; // first smpl = (1/4) bit | |
// dlthb() ; // wait a half bit period | |
dlihb() ; // wait a half bit period | |
if(!(PIND & (1<<PD7))) // sample at 3/4 bit | |
{ eep_buf &= ~bitmask ; } // if (3/4)bit = 0 --> bit = 0 | |
else { eep_buf|=bitmask ; } // if (3/4)bit = 1 --> bit = 1 | |
dliqb() ; // final quarter bit delay | |
bitmask = bitmask >>1 ; } // shift right mask for 8 bits | |
DDRD |= (1<<PD7) ; return eep_buf ; } // pin = out , return data buffer | |
//.............................................................................. | |
void uni_wrmns(void) // write + MAK + NOSAK | |
{ eep_buf = START ; uni_wr() ; // stream out 'START' previously loaded | |
mak() ; nosak() ; } // master ACK + slave NOACK | |
//........................................................................... | |
void uni_wrms(unsigned char ms) // write + MAK + SAK | |
{ eep_buf = ms ; uni_wr() ; // stream out 'eep_buf' previously loaded | |
mak() ; // master ACK | |
sak() ; // slave ACK | |
// sakq() ; // slave ACK (quarter bit) | |
} | |
//........................................................................... | |
void uni_wrnms(unsigned char nms) // write + NOMAK + SAK | |
{ eep_buf = nms ; uni_wr() ; // stream out 'eep_buf' previously loaded | |
nomak() ; // master NOACK | |
sak() ; // slave ACK | |
// sakq() ; // slave ACK ( quarter bit ) | |
} | |
// ¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// UNIO HEADER FUNCTIONS | |
// ............................................................................ | |
void uni_head(void) // first time , after POR | |
{ | |
PORTD &= ~(1<<PD7) ; // clear pin | |
dlythdr() ; // Thdr delay | |
PORTD |= (1<<PD7) ; // set pin | |
dlystby() ; // Tstby delay | |
PORTD &= ~(1<<PD7) ; // clear pin ( before START ) | |
dlythdr() ; } // Thdr | |
//.............................................................................. | |
void uni_head2(void) // for consecutive commands | |
{ PORTD |= (1<<PD7) ; // set pin | |
dlytss() ; // Tss delay | |
PORTD &= ~(1<<PD7) ; // clear pin ( before START ) | |
dlythdr() ; } // Thdr | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// UNIO COMMAND FUNCTIONS | |
//.............................................................................. | |
void uni_cmnd(unsigned char cmnd) // WREN , WRDI , ERAL , SETAL | |
{ uni_head() ; // perform the POR header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x04 ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x05 ; | |
uni_wrnms(cmnd) ; } // end with : wr(cmnd) + nomak + sak | |
//.............................................................................. | |
void uni_cmnd2(unsigned char cmnd) // WREN , WRDI , ERAL , SETAL | |
{ uni_head2() ; // perform the 2nd header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x04 ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x05 ; | |
uni_wrnms(cmnd) ; } // end with : wr(cmnd) + nomak + sak | |
//............................................................................... | |
void uni_eral(void) // erase entire array (00) | |
{ uni_cmnd(WREN) ; // ERAL needs WREN | |
uni_cmnd(ERAL) ; // ERAL command | |
dly5ms() ; dly5ms() ; } // ERAL/SETAL need 10ms Twc | |
// Not yet tested on this micro. For more details see the data sheet of the | |
// memory and the related app note (AN1184) - UNIO on 8051 + asm | |
//............................................................................... | |
void uni_eral2(void) // erase entire array(00)-consecutive cmnd | |
{ uni_cmnd2(WREN) ; // ERAL needs WREN | |
uni_cmnd2(ERAL) ; // ERAL command | |
dly5ms() ; dly5ms() ; } // ERAL/SETAL need 10ms Twc | |
// Not yet tested on this micro. For more details see the data sheet of the | |
// memory and the related app note (AN1184) - UNIO on 8051 + asm | |
//............................................................................... | |
void uni_setal(void) // set entire array (ff) | |
{ uni_cmnd(WREN) ; // SETAL needs WREN | |
uni_cmnd(SETAL) ; // SETAL command | |
dly5ms() ; dly5ms() ; } // ERAL/SETAL need 10ms Twc | |
// Not yet tested on this micro. For more details see the data sheet of the | |
// memory and the related app note (AN1184) - UNIO on 8051 + asm | |
//............................................................................... | |
void uni_setal2(void) // set entire array(ff)-consecutive cmnd | |
{ uni_cmnd2(WREN) ; // SETAL needs WREN | |
uni_cmnd2(SETAL) ; // SETAL command | |
dly5ms() ; dly5ms() ; } // ERAL/SETAL need 10ms Twc | |
// Not yet tested on this micro. For more details see the data sheet of the | |
// memory and the related app note (AN1184) - UNIO on 8051 + asm | |
//............................................................................... | |
void uni_wrsr(unsigned char stat) // write to status register (after POR) | |
{ uni_head() ; // perform the first header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x01 ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x02 ; | |
uni_wrms(WRSR) ; // wr(WRSR) + mak + sak | |
err_cnt = 0x03 ; | |
uni_wrnms(stat) ; // end with : wr + nomak + sak | |
dly5ms() ; } // 5msec = Twc | |
// The list of error messages is presented in the 'main' function. | |
//.............................................................................. | |
void ini_unio(void) | |
{ uni_wrsr(NOPROT) ; // write in status reg - NOPROT = 00 | |
} // disable all write protections | |
//.............................................................................. | |
unsigned char uni_rdsr(void) // read the status register | |
{ uni_head2() ; // (second) consecutive header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
uni_wrms(RDSR) ; // wr(RDSR) + mak + sak | |
uni_rdq() ; // eep_buf = status reg | |
// uni_rd3q() ; | |
nomak() ; // master NOACK | |
// sakq() ; // SAK with quarter bit sampling | |
sak() ; // SAK with normal sampling | |
return eep_buf ; } // return the result of uni_rdq | |
//.............................................................................. | |
void uni_wippol(void) // polling of WIP flag = bit0 of SR | |
{ while(uni_rdsr()&0x01) ; // wait the flag to be cleared by hw | |
} // may replace Twc | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// UNIO BYTE ACCESS FUNCTIONS | |
// The list of error messages is presented in the 'main' function. | |
//.............................................................................. | |
void uni_wrbyte(unsigned int eep_adr, unsigned char eep_data) | |
{ // writes a byte at the spec address | |
uni_cmnd2(WREN) ; // first, enable writes, consecutive cmnd | |
uni_head2() ; // 2nd header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x06 ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x07 ; | |
uni_wrms(WRITE) ; // wr(WRITE) + mak + sak | |
err_cnt = 0x08 ; | |
uni_wrms(eep_adr>>8) ; // wr(eep_adr>>) + mak + sak | |
uni_wrms(eep_adr&0xff) ; // wr(eep_adr&0xff) + mak + sak | |
err_cnt = 0x0a ; | |
uni_wrnms(eep_data) ; // wr(eep_data) + nomak + sak | |
dly5ms() ; // write cycle time after each byte | |
// uni_wippol() ; // pol WIP flag as Twc | |
} | |
//........................................................................... | |
void uni_rdbyte(unsigned int eep_adr, unsigned char *dst) | |
{ // reads a byte from the spec adr | |
uni_head2() ; // 2nd header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x0b ; | |
uni_wrms(DEVADR) ; // wr + mak + sak | |
err_cnt = 0x0c ; | |
uni_wrms(READ) ; // wr + mak + sak | |
err_cnt = 0x0d ; | |
uni_wrms(eep_adr>>8) ; // wr + mak + sak | |
uni_wrms(eep_adr&0xff) ; // wr + mak + sak | |
err_cnt = 0x0f ; | |
uni_rdq() ; // eep_buf = read data byte | |
// don't loose time storing now the result | |
// uni_rd3q() ; | |
nomak() ; // master noack | |
sak() ; // slave ack | |
// sakq() ; // slave ack ( quarter bit ) | |
*dst = eep_buf ; // store read byte in the end | |
} | |
//........................................................................... | |
void uni_crrdbyte(unsigned char *dst) | |
{ // reads a byte from the crt adr | |
uni_head2() ; // 2nd header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x0b ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x0c ; | |
uni_wrms(CRRD) ; // wr(CRRD) + mak + sak | |
err_cnt = 0x0f ; | |
uni_rdq() ; // eep_buf = read data byte | |
// don't loose time storing now the result | |
// uni_rd3q() ; | |
nomak() ; // master noack | |
sak() ; // slave ack | |
// sakq() ; // slave ack (quarter bit) | |
*dst = eep_buf ; // store read byte in the end | |
} | |
// Not yet tested on this micro. For more details see the data sheet of the | |
// memory and the related app note (AN1184) - UNIO on 8051 + asm | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// UNIO STRING ACCESS FUNCTIONS | |
//........................................................................... | |
void uni_wrstr(unsigned char *source,unsigned int eep_adr,unsigned char lofsstr) | |
// writes a string at the spec addr ; the length of the string(source) must be : | |
// lofsstr = [2 - 16] ; for single byte strings use "uni_wrbyte" | |
{ | |
unsigned char k = 0 ; ; // init char counter inside the string | |
copystr(load,source,lofsstr) ; // bring inside the function the string | |
uni_cmnd2(WREN) ; // enable writes | |
uni_head2() ; // header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x06 ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x07 ; | |
uni_wrms(WRITE) ; // wr(WRITE) + mak + sak | |
err_cnt = 0x08 ; | |
uni_wrms(eep_adr>>8) ; // wr(eep_adr>>8) + mak + sak | |
uni_wrms(eep_adr&0xff) ; // wr(eep_adr&0xff) + mak + sak | |
err_cnt = 0x09 ; | |
while(k<lofsstr-1) // for (n-1) bytes | |
{ uni_wrms(load[k]) ; k++ ; } // wr(bytes) + mak + sak | |
err_cnt = 0x0a ; | |
uni_wrnms(load[k]) ; // wr(last byte) + nomak + sak | |
dly5ms() ; // final write cycle time | |
// uni_wippol() ; // polling WIP flag | |
} | |
//............................................................................. | |
void uni_rdstr(unsigned char *dest,unsigned int eep_adr,unsigned char lofdstr) | |
// reads a string from the spec addr ; the length of the destination string | |
// must be : lofdstr = [ 2 - 16 ] ; for single byte strings use "uni_rdbyte" | |
{ | |
unsigned char k = 0 ; ; // init char counter inside the string | |
uni_head2() ; // 2nd header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x0b ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x0c ; | |
uni_wrms(READ) ; // wr(READ) + mak + sak | |
err_cnt = 0x0d ; | |
uni_wrms(eep_adr>>8) ; // wr(eep_adr>>8) + mak + sak | |
uni_wrms(eep_adr&0xff) ; // wr + mak + sak | |
err_cnt = 0x0e ; | |
while(k<lofdstr-1) // for (n-1) bytes | |
{ | |
uni_rdq() ; // eep_buf = read bytes | |
// uni_rd3q() ; | |
// don't loose time now to store data | |
mak() ; // master ACK | |
sak() ; // slave ACK | |
// sakq() ; // slave ACK with quarter bit | |
load[k] = eep_buf ; k++ ; } // store locally data, incr counter | |
err_cnt = 0x0f ; | |
uni_rdq() ; // eep_buf = last read byte | |
// uni_rd3q() ; | |
nomak() ; // master NOACK | |
sak() ; // slave ACK | |
// sakq() ; // slave ACK , quarter bit | |
load[k] = eep_buf ; // store locally last byte | |
copystr(dest,load,lofdstr) ; // internal string(load)-->dest | |
} | |
//.............................................................................. | |
void uni_crrdstr(unsigned char *dest,unsigned char lofdstr) | |
// reads a string from the crt addr ; the length of the destination string | |
// must be : lofdstr = [ 2 - 16 ] ; for single byte strings use "uni_crrdbyte" | |
{ | |
unsigned char k = 0 ; // init char counter inside the string | |
uni_head2() ; // 2nd header of the protocol | |
uni_wrmns() ; // wr(START) + mak + nosak | |
err_cnt = 0x0b ; | |
uni_wrms(DEVADR) ; // wr(DEVADR) + mak + sak | |
err_cnt = 0x0c ; | |
uni_wrms(READ) ; // wr(READ) + mak + sak | |
err_cnt = 0x0e ; | |
while(k<lofdstr-1) // for (n-1) bytes | |
{ | |
uni_rdq() ; // eep_buf = read bytes | |
// uni_rdq() ; | |
// don't loose time now to store data | |
mak() ; // master ACK | |
sak() ; // slave ACK | |
// sakq() ; // slave ACK with quarter bit | |
load[k] = eep_buf ; k++ ; } // store locally data, incr counter | |
err_cnt = 0x0f ; | |
uni_rdq() ; // eep_buf = last read byte | |
// uni_rd3q() ; | |
nomak() ; // master NOACK | |
sak() ; // slave ACK | |
// sakq() ; // slave ACK , quarter bit | |
load[k] = eep_buf ; // store locally last byte | |
copystr(dest,load,lofdstr) ; // internal string(load)-->dest | |
} | |
// Not yet tested on this micro. For more details see the data sheet of the | |
// memory and the related app note (AN1184) - UNIO on 8051 + asm | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// UNIO AUXILIARY FUNCTIONS | |
//.............................................................................. | |
void dltim(unsigned int steps) | |
{ // delay through timer_A <10Mhz> | |
/* | |
// offset=4us, step=0.1us | |
TACTL = MC_0 + TACLR ; // stop and clear timer | |
CCR1 = steps ; // load delay value | |
TACTL = TASSEL_2 + MC_2 ; // SMCLK + continous mode | |
while(!(CCTL1 & CCIFG)) ; // wait CCIFG | |
CCTL1 &= ~CCIFG ; // clear CCIFG | |
TACTL = TASSEL_2 + MC_0 ; // stop timer | |
*/ | |
} | |
//.............................................................................. | |
void dlins(unsigned int steps) | |
{ // delay through instructions | |
unsigned int k ; // offset=2us , step=0.5us | |
for(k=0;k<steps;k++) | |
{;} } | |
void calcdly(void) // tqb , thb , iqb , ihb | |
{ | |
tqb = QBT - 40 ; // quarter bit ( timer ) | |
thb = 2*QBT - 40 ; // half bit ( timer ) | |
iqb = QBI - 4 ; // quarter bit ( instr ) | |
ihb = 2*QBI - 4 ; // half bit ( instr ) | |
} | |
//................................................................................. | |
void dlthb(void) | |
{ | |
/* // delay HB through timer | |
// offset=4us, step=0.1us | |
TACTL = MC_0 + TACLR ; // stop and clear timer | |
CCR1 = thb ; // load delay value hf bit | |
TACTL = TASSEL_2 + MC_2 ; // SMCLK + continous mode | |
while(!(CCTL1 & CCIFG)) ; // wait CCIFG | |
CCTL1 &= ~CCIFG ; // clear CCIFG | |
TACTL = TASSEL_2 + MC_0 ; // stop timer | |
*/ | |
} | |
//.............................................................................. | |
void dltqb(void) | |
{ // delay QB through timer | |
/* // offset=4us, step=0.1us | |
TACTL = MC_0 + TACLR ; // stop and clear timer | |
CCR1 = tqb ; // load delay value hf bit | |
TACTL = TASSEL_2 + MC_2 ; // SMCLK + continous mode | |
while(!(CCTL1 & CCIFG)) ; // wait CCIFG | |
CCTL1 &= ~CCIFG ; // clear CCIFG | |
TACTL = TASSEL_2 + MC_0 ; // stop timer | |
*/ } | |
//.............................................................................. | |
void dlihb(void) | |
{ // delay HB through instructions | |
unsigned int k ; // offset=2us , step=0.5us | |
for(k=0;k<ihb;k++) {;} } // | |
//............................................................................... | |
void dliqb(void) | |
{ // delay QB through instructions | |
unsigned int k ; // offset=2us , step=0.5us | |
for(k=0;k<iqb;k++) {;} } // | |
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
void dlythdr(void) // short low pulse before START | |
{ | |
dltim(100) ; // 100 timer steps = 10us | |
// dlins(20) ; // 20 instr steps = 10 us | |
} | |
//............................................................................... | |
void dlytss(void) // short high pulse for consecutive cmnds | |
// instead STBY | |
{ dltim(400) ; } // 400 timer steps = 40us | |
//............................................................................... | |
void dlystby(void) | |
{ dltim(8000) ; } // 8,000 timer steps = 800us(>600us) | |
//............................................................................... | |
void dly5ms(void) | |
{ dltim(50000) ; } // 50,000 timer steps = 5,000us = 5ms | |
//............................................................................... | |
void dly250ms(void) | |
{ unsigned char k = 50 ; // 50 * 5ms = 250 ms | |
while(--k) { dly5ms() ; } } // usefull for messages display | |
//............................................................................... | |
void dly1s(void) | |
{ dly250ms() ; dly250ms() ; | |
dly250ms() ; dly250ms() ; } // 4 * 250 ms = 1 sec | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
void final_error(void) // final error , for low level functions | |
{ | |
// while(1){ | |
// LED_6 = ~err_cnt; | |
// dly1s(); // LEDs active on "0" | |
// LED_6 = 0xff ; | |
// dly1s() ; | |
// } | |
} | |
//................................................................................ | |
void copystr(unsigned char d[],unsigned char s[],unsigned char strsz) | |
{ unsigned char n ; | |
for(n=0;n<strsz;n++) | |
{ d[n]=s[n] ; } } // copy source in destination | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// MAIN FUNCTION | |
//................................................................................ | |
// A 4 bits counter displayed on LEDs means that everything is OK : | |
// no errors in the low level functions, reads = writes. | |
// A 2Hz blinking (00-0f) means that the code didn't detect any error in low level | |
// functions, but reads <> writes. | |
// A 0.5Hz blinking ( 00 - 01, 00 - 02 , ... , 00 - 0f ) detects an error in | |
// a low level function . The related error_list is presented down the page. | |
void loop(){ | |
#define ADR0 0x0020 // initialization of the address | |
#define RND_MODE 0 // random byte access mode | |
#define PG_MODE 1 // page access mode | |
// .......................................................................... | |
unsigned char access_mode = RND_MODE ; // set the access mode to RAND | |
// unsigned char access_mode = PG_MODE ; // set the access mode to PAGE | |
unsigned int adr_cnt ; // address counter | |
unsigned char ch_cnt ; // character counter inside strings | |
unsigned char src_str[17] = "UNI_MSP_CCC_BB.C" ; | |
// source string which will be written | |
// UNI = UNIO protocol - MSP=MSP430 family | |
// CCC = "C" language , BB = bitbang meth | |
unsigned char dst_str[STRSZ]; // destination string,read from the eep | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
while(1) | |
{ | |
/* | |
// call all initialization routines | |
ini_wdt() ; // W.D.T.'s init | |
ini_rosc() ; // oscillator's init-RCosc-Rext=100k | |
ini_gpio() ; // GPIO's init | |
ini_tim() ; // Timers' init | |
calcdly() ; // calculates externally values of dlys | |
// do not loose time inside functions | |
*/ | |
//............................................................................ | |
// below, few test functions for delays (through instructions & timer) | |
// keep in mind that : main clock ~ 10Mhz ( overclock ) | |
// tqb = QBT - 40 / thb = 2*QBT - 40 (100ns resolution & 4us offset) | |
// iqb = QBI - 04 / ihb = 2*QBI - 04 (0.5us resolution & 2us offset) | |
// long delays are performed through timer_A | |
// short delays are performed through timer or instructions | |
// QBT_max = 0xa0 = 160 * 100ns ~ 16us ( bit > 64us [ < 015Khz ] ) | |
// QBT_min = 0x28 = 040 * 100ns ~ 04us ( bit > 16us [ < 060Khz ] ) | |
// QBI_max = 0x20 = 032 * 500ns ~ 16us ( bit > 64us [ < 015Khz ] ) | |
// QBI_min = 0x04 = 004 * 500ns ~ 02us ( bit > 08us [ < 125Khz ] ) | |
//............................................................................ | |
goto ini ; | |
// goto s1 ; // jmp to 1sec LEDs toggle | |
// goto ms250 ; // jmp to 0.25sec LEDs toggle | |
// goto tim ; // jmp to short delays through timer | |
goto ins ; // jmp to short delays through instructions | |
// goto ms5 ; // jmp to 5msec delay through timer | |
s1: while(1) | |
{ LED_6 = 0x00 ; dly1s() ; // toggle LEDs at a rate | |
LED_6 = 0x0f ; dly1s() ; } // of 1 second | |
ms250: while(1) | |
{ LED_6 = 0x00 ; dly250ms() ; // toggle LEDs at a rate | |
LED_6 = 0x0f ; dly250ms() ; } // of 0.25 seconds | |
tim: while(1) | |
{ PORTD ^= (1 << PD7) ; dltqb() ; // toggle PORTD,7 at QB timer | |
PORTD ^= (1 << PD7) ; dltqb() ; // toggle PORTD,7 at QB timer | |
PORTD ^= (1 << PD7) ; dlthb() ; // toggle PORTD,7 at HB timer | |
PORTD ^= (1 << PD7) ; dltqb() ; // toggle PORTD,7 at QB timer | |
} | |
ins: while(1) | |
{ PORTD ^= (1 << PD7) ; dliqb() ; // toggle PORTD,7 at QB instructions | |
PORTD ^= (1 << PD7) ; dliqb() ; | |
PORTD ^= (1 << PD7) ; dlihb() ; // toggle PORTD,7 at HB instructions | |
PORTD ^= (1 << PD7) ; dliqb() ; | |
} | |
ms5: while(1) | |
{ PORTD ^= (1 << PD7) ; dly5ms() ; // toggle PORTD,7 at 5msec | |
PORTD ^= (1 << PD7) ; dliqb() ; dly5ms(); } | |
//........................................................................... | |
ini: ini_unio() ; // INIT UNIO memory | |
// write(#00)-->status register | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// WRITE SOURCE STRING IN EEPROM | |
//............................................................................ | |
if(access_mode==RND_MODE) // if RANDOM MODE | |
{ ch_cnt=0 ; adr_cnt=ADR0 ; // initialize char & address counters | |
while(ch_cnt<STRSZ) // repeat till the end of the string | |
{uni_wrbyte(adr_cnt,src_str[ch_cnt]); // write a random byte | |
ch_cnt++ ; adr_cnt++ ; } } // increment both counters | |
else // if PAGE MODE | |
{uni_wrstr(src_str,ADR0,STRSZ) ; } // write (page mode) from the source | |
// string , beginning from ADR0 address | |
// length of the string = STRSZ | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// READ EEPROM IN THE DESTINATION STRING | |
// ............................................................................ | |
if(access_mode==RND_MODE) // in RANDOM MODE | |
{ch_cnt=0 ; adr_cnt=ADR0 ; // init both counters : char & address | |
while(ch_cnt < STRSZ) // repeat till the end of the string | |
{uni_rdbyte(adr_cnt,dst_str+ch_cnt); // fill the destination string with chrs | |
ch_cnt++ ; adr_cnt++ ; } } // increment both counters (chr&address) | |
else | |
{uni_rdstr(dst_str,ADR0,STRSZ) ; } // in PAGE MODE , sequential read | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// COMPARE SOURCE & DESTINATION STRINGS | |
//............................................................................ | |
for(ch_cnt=0;ch_cnt<STRSZ;ch_cnt++) | |
{if((*(dst_str+ch_cnt)) != (*(src_str+ch_cnt))) | |
// compare the 2 strings(source & dest) | |
{ | |
// while(1) // in case of mismatch | |
{LED_6 = 0x00 ; dly250ms() ; // flash forever 00 - 0f , 4 / second | |
LED_6 = 0x0f ; dly250ms() ; } } // on P1 (4 LEDs) | |
else {LED_6 = ~ch_cnt ; // if coincidence,display counter on LEDs | |
dly250ms() ; // 4 bytes /second for a visual control | |
} } // repeat till the end of the string | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// while(1) // as final sign of sucess, display | |
for(ch_cnt=0;ch_cnt<16;ch_cnt++) // on LEDs (infinetelly) a counter | |
{ LED_6 = ~ch_cnt ; dly250ms() ; } // 4 bytes / second | |
} | |
digitalWrite(6,HIGH); | |
dly250ms(); | |
digitalWrite(6,LOW); | |
} // END MAIN | |
//¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬ | |
// LIST OF ERROR MESSAGES | |
//............................................................................. | |
// error_01 = WRSR-DEVADR error_02 = WRSR-WRSR cmnd error_03 = wr to SREG | |
// error_04 = WREN-DEVADR error_05 = WREN-WREN cmnd | |
// error_06 = WRITE-DEVADR error_07 = WRITE-WRITE cmnd error_08 = WRITE-address | |
// error_09 = WRITE-(n-1)DB error_10 = WRITE last data byte ( or random byte ) | |
// error_11 = READ-DEVADR error_12 = READ-READ cmnd error_13 = READ-address | |
// error_14 = READ-(n-1)DB error_15 = READ last byte ( or random byte ) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment