// Program FL_EE.C, Sourceboost C, PIC16F887, ICD2
//
// Illustrates how to write to and read from flash EEPROM memory. Note
// that this is 14-bits wide.
//
// The program is simplified to log data by repeatedly calling a stub make_meas
// which generates four words and saving these to flash EEPROM beginning at
// location 0x1000. Each of these four words is displayed on the serial LCD
// using a 'M' (meas) delimiter.
//
// These four word blocks of data are sequentially written to EEPROM by reading
// a 16 word block, inserting the four word block and then programming the 16
// word block.
//
// The program memory is then displayed by reading four word blocks. Note that
// the delimiter 'D' is used to indicate the "dump" code is being executed.
//
// copyright, Peter H. Anderson, Baltimore, MD, July, '09
#include <system.h>
#include <icd2.h>
#include <string.h>
#include <stdio.h>
#pragma DATA 0x2007, 0x28e4
#pragma DATA 0x2008, 0x3eff
#pragma CLOCK_FREQ 4000000
#define NEGATIVE 1
#define POSITIVE 0
#define TRUE !0
#define FALSE 0
//#define DEBUG
typedef unsigned char byte;
void log_data(void);
void dump_data(void);
void make_meas(int *data, byte num_words);
void write_flash_eeprom(int write_address, int *data, byte num_words);
void read_flash_eeprom(int read_address, int *data, byte num_words);
void print_str(char *s);
void print_ch(char ch);
void print_ints(int *d, byte num, char ch);
void asynch_setup(void);
void main(void)
{
asynch_setup();
while(1)
{
log_data();
dump_data();
}
}
void log_data(void)
{
byte n;
int data[16];
int write_address = 0x1000;
for (n=0; n<25; n++) // 100 words
{
make_meas(data, 4);
write_flash_eeprom(write_address, data, 4);
write_address += 4;
}
}
void dump_data(void)
{
byte m, n;
int data[16], read_address = 0x1000;
for (n=0; n<25; n++)
{
read_flash_eeprom(read_address, data, 4);
print_ints(data, 4, 'D');
read_address += 4;
}
}
void write_flash_eeprom(int write_address, int *data, byte num_bytes)
{
int base_address, save_buffer[16];
byte n, offset;
base_address = write_address & 0xfff0; // zero the least signif 4 bits
offset = write_address & 0x000f;
eecon1.EEPGD = 1; // flash data
read_flash_eeprom(base_address, save_buffer, 16); // fetch what is in the 16 byte block
// print_ints(save_buffer, 16, 'W');
// now insert the new data
for (n=0; n<num_bytes; n++)
{
save_buffer[n+offset] = data[n];
}
eeadrh = (byte) (base_address >> 8);
eeadr = (byte) (base_address & 0xff);
for (n=0; n<16; n++)
{
eedath = save_buffer[n] >> 8;
eedata = save_buffer[n] & 0xff;
eecon1.EEPGD = 1;
eecon1.WREN = 1;
// disable interrupts
eecon2 = 0x55;
eecon2 = 0xaa;
eecon1.WR = 1;
asm
{
NOP
NOP
}
eecon1.WREN = 0;
// okay to enable ints
++eeadr;
}
}
void read_flash_eeprom(int read_address, int *data, byte num_words)
{
byte n, h, l;
for (n=0; n<num_words; n++)
{
eeadrh = (byte) (read_address >> 8);
eeadr = (byte) (read_address & 0xff);
eecon1.EEPGD = 1; // flash data
eecon1.RD = 1;
asm
{
NOP
NOP
NOP
NOP
NOP
NOP
}
h = eedath; l = eedata;
data[n] = (((int) h) << 8) | l;
++read_address;
}
}
void make_meas(int *data, byte num_words)
{
static byte m = 0;
byte n;
for (n=0; n<num_words; n++)
{
data[n] = m * 100 + 4 * n;
}
++m;
m = (m==20) ? 0 : m;
print_ints(data, 4, 'M');
delay_s(2);
}
void asynch_setup(void)
{ // for UART, see Manual pages beginning at page 151
trisc.7 = 1;
trisc.6 = 1; // TX
rcsta.SPEN = 1; // enable serial port
txsta.TXEN = 1; // enable transmitter
txsta.SYNC = 0; // asynchronous
txsta.BRGH = 1;
spbrg = 25; // 9600 baud at 4.0 MHz
}
void print_ints(int *d, byte num, char ch)
{
byte i, j;
char s[20];
strcpy(s, "?f");
print_str(s);
for (i=0; i<num; i++)
{
sprintf(s, "%u", d[i]);
print_str(s);
print_ch(ch); // distictive delimiter
if (((i % 4) == 0) && (i!=0))
{
strcpy(s, "?n");
print_str(s);
}
}
delay_s(1);
}
void print_str(char *s)
{
while(*s != '\0')
{
txreg = *s;
while(txsta.TRMT == 0)
{
}
++s;
}
}
void print_ch(char ch)
{
txreg = ch;
while(txsta.TRMT == 0)
{
}
}