Skip to content

Instantly share code, notes, and snippets.

@monsonite
Created June 9, 2011 13:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save monsonite/1016689 to your computer and use it in GitHub Desktop.
Save monsonite/1016689 to your computer and use it in GitHub Desktop.
// 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