eeprom redundant-values routines

View: New views
11 Messages — Rating Filter:   Alert me  

eeprom redundant-values routines

by Dwayne Reid :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Good day to all.

I'm getting started on a project that requires a few bytes of
eeprom.  The target is a 12F675.

I recall recent discussion (and past discussions) about the problem
of multiple writes causing eventual read failures of static eeprom
values (static as in they don't change often or at all).  Bob Axtell
mentions that he gets around the problem by storing 5 redundant
values and checking them upon reading.

This sounds like it might be a good idea.

With that in mind, I started writing code.  Its somewhat more
complicated than I first thought.

I'd like to post my routines for any thoughts or criticisms.  In
particular, I'd like to find shorter or faster methods of doing the same thing.

In a nutshell, this is a pair of subroutines.  The main code calls
ReadEEredundant with the starting address in W.  The routine returns
with the Z=1 and the value read from eeprom in W if everything was
OK.  It returns Z=0 if it can't find 3 identical bytes in the 5
locations (fatal error).

ReadEEredundant makes use of another subroutine as part of its
operation.  The whole thing uses 2 levels of stack.

If ReadEEredundant finds one or more bad bytes out of the 5 but does
find at least 3 values the same, it re-writes all 5 bytes.

Before I post the code, I should mention the conventions that I use
when writing my code.

RB1(value) is a macro that writes that value to ram page 1
BB1(_value) is another macro that sets or clears individual bits on ram page 1
The above macros are mostly to ensure that I get adequate warning if
I mess up writing to the wrong ram page.

Individual bits are defined with a leading underscore.

SUBTMP1 through SUBTMP3 are temporary values used in subroutines and
are on ram page 0
SUBTMP1_0 through SUBTMP1_3 are the same but on ram page 1

I realize that user ram on the 12F675 is the same on both ram page 0
& ram page 1 but I tend to write my code for the other PICs that I use.

rampg0 is a macro that sets the ram page select bits to ram page 0
rampg1 is a macro that sets the ram page select bits to ram page 1
tstw is a 1 line macro that sets or clears the Z flag based on the
value contained in W (xorlw 0)

Finally, I need to mention that this is a first pass on the
code.  While it assembles cleanly, I haven't yet fully tested
it.  There may be some stupid errors in there.

All that said: here's the code.  Again, these are subroutines that
are intended to be called by the main loop.

ReadEEredundant ;read EE value stored in 5 redundant locations
                 ;enters with start address in W
                 ;returns with EE value in W, Z=0 if OK, z=1 if fail
;read redundant eeprom value, re-write value if corrupted
     rampg1      ;this whole routine uses ram pg 1
     movwf       SUBTMP1_0       ;save start location
     movwf       RB1(EEADR)
     movlw       .4              ;# bytes to compare to
     movwf       SUBTMP1_1       ;loop counter

     movfw       SUBTMP1_0       ;start with 1st byte
     call        ReadRedund      ;returns: 0x00=perfect, 0x01=1st OK, 0xFF=bad
     tstw
     bz          NoReadErrors    ;all 5 values identical

;one or more read errors have occurred
;2 choices here: 1st byte is OK **or** 1st byte doesn't match at least 2 others
     xorlw       0x01
     bz          ReadEErewrite   ;fewer than 3 errors: rewrite array

;1st byte doesn't match 2 other bytes: try starting with 2nd byte
     movlw       .3              ;# bytes to compare to
     movwf       SUBTMP1_1       ;loop counter

     incf        SUBTMP1_0,W     ;start with 2nd byte
     call        ReadRedund      ;returns: 0x01=1st OK, 0xFF=bad

;2 choices: 2nd byte is OK **or** 2nd byte doesn't match at least 2 others
     xorlw       0x01
     bz          ReadEErewrite   ;fewer than 3 errors: rewrite array

;2nd byte doesn't match 2 other bytes: try last (3rd) byte
     movlw       .2              ;# bytes to compare to
     movwf       SUBTMP1_1       ;loop counter

     movlw       .2              ;start with 3rd byte
     addwf       SUBTMP1_0,W
     call        ReadRedund      ;returns: 0x01=1st OK, 0xFF=bad

;2 choices: 3rd byte is OK **or** 3rd byte doesn't match at least 2 others
     xorlw       0x01
     bz          ReadEErewrite   ;fewer than 3 errors: rewrite array

;fatal error: no 3 bytes identical
     rampg0
     clrz
     retlw       0xFF            ;Bad data.  Returns z=0

NoReadErrors
     movfw       SUBTMP1_3       ;
     rampg0
     setz
     return                      ;returns with known-good value in W, z=1


ReadEErewrite   ;re-write entire block of 5 bytes with known-good data
                 ;still in ram pg 1
     movfw       SUBTMP1_3       ;retrieve known-good data
     movwf       RB1(EEDATA)
     movfw       SUBTMP1_0       ;starting address
     movwf       RB1(EEADR)
     movlw       .5              ;write all 5 bytes
     movwf       SUBTMP1_1

ReadEErewriteLoop
     rampg0
     movlw       INT_EEWRITE     ;clr all bits except PEIE
     movwf       INTCON
     bcf         _EEIF
     rampg1
     movlw       PIE1_EEWRITE    ;clr all bits except EEIE
     movwf       RB1(PIE1)

     bsf         BB1(_WREN)      ;EE write enable
     movlw       0x55            ;EE un-lock sequence
     movwf       RB1(EECON2)
     movlw       0xAA
     movwf       RB1(EECON2)
     bsf         BB1(_WR)        ;initiate write
     bcf         BB1(_WREN)      ;clear EE write enable

     sleep                       ;GIE=0, all others =0 except PEIE & EEIE

     incf        RB1(EEADR),F    ;next address
     decfsz      SUBTMP1_1,F
       goto      ReadEErewriteLoop

     movlw       PIE1_INIT
     movwf       RB1(PIE1)       ;restore PIE1
     movfw       SUBTMP1_3       ;known-good value
     rampg0
     movwf       SUBTMP1         ;save value from rampg1 to rampg0
     movlw       INT_INIT
     movwf       INTCON          ;restore INTCON
     movfw       SUBTMP1
     setz
     return                      ;done!  Returns with value in W, Z=1 if OK


ReadRedund      ;enters with comparison byte address in W
                 ;returns: 0x00=perfect, 0x01= 1st byte OK, 0xFF= bad
                 ;still in ram pg 1
     movwf       RB1(EEADR)
     bsf         BB1(_RD)
     movfw       RB1(EEDATA)     ;W contains comparison byte
     movwf       SUBTMP1_3       ;save for exit
     clrf        SUBTMP1_2       ;bytes-the-same-value register (bit mapped)

ReadRedundLoop
     clrc
     incf        RB1(EEADR),F    ;point to next address
     bsf         BB1(_RD)
     xorwf       RB1(EEDATA),W   ;same as 1st address?
     skpnz
       setc
     xorwf       RB1(EEDATA),W   ;restore W
     rlf         SUBTMP1_2,F

     decfsz      SUBTMP1_1,F
       goto      ReadRedundLoop

;fall into GetEE_Error
GetEE_Error     ;"1" bits means match with 1st (comparison) byte
     movfw       SUBTMP1_2
     addwf       PCL,W
     skpnc
       incf      PCLATH,F
     movwf       PCL             ;need to match at least 2 bytes (3 total)
     retlw       0xFF            ;b'xxxx0000'
     retlw       0xFF            ;b'xxxx0001'
     retlw       0xFF            ;b'xxxx0010'
     retlw       0x01            ;b'xxxx0011'
     retlw       0xFF            ;b'xxxx0100'
     retlw       0x01            ;b'xxxx0101'
     retlw       0x01            ;b'xxxx0110'
     retlw       0x01            ;b'xxxx0111'
     retlw       0xFF            ;b'xxxx1000'
     retlw       0x01            ;b'xxxx1001'
     retlw       0x01            ;b'xxxx1010'
     retlw       0x01            ;b'xxxx1011'
     retlw       0x01            ;b'xxxx1100'
     retlw       0x01            ;b'xxxx1101'
     retlw       0x01            ;b'xxxx1110'
     retlw       0x00            ;b'xxxx1111'  No errors


As I mentioned, I'd be interested in other (easier) ways of doing the
same thing.

Many thanks!

dwayne

--
Dwayne Reid   <dwayner@...>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
www.trinity-electronics.com
Custom Electronics Design and Manufacturing

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by M. Adam Davis-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Oct 28, 2009 at 10:46 PM, Dwayne Reid <dwayner@...> wrote:
> I recall recent discussion (and past discussions) about the problem
> of multiple writes causing eventual read failures of static eeprom
> values (static as in they don't change often or at all).

If the data doesn't change, don't initiate an EEPROM write.  Only
write it on change.  This should eliminate this concern.

However, in high reliability scenarios, five copies is perhaps
overkill, and the way you are doing the write may be prone to problems
related to power off conditions (ie, since all five bytes are being
written you may run into issues regarding the validity of data if the
write is in process when the unit loses power).

You must seperate your writes in both time and space - they should not
be immediately adjacent, and the writes should not occur at the same
time.

Further, you would be better off adopting a CRC and a counter for each
redundant value (or redundant datablock).  This gives you confidence
the value is correct (error checking), and that it's the latest value
stored (coherence).

For example:

In one high reliability, safety critical industry the most critical
information is kept in three locations, everything else is stored in
only two locations.  Each time the value is changed the counter is
incremented, the CRC calculated over both the value and the counter,
and the first redundant copy is written.  If anything fails during
this write, the second copy still has the older value, and the CRC
ensures that this one won't be used.  Once the first copy is finished
writing, a routine verifies it.  Then the counter is incremented, the
CRC recalculated, and the second copy is written and verified.  Again,
if anything fails during this write then the first copy is known good,
and the counter verifies that it's the latest.  If a third copy is
made, then the same process happens all over again.

On boot up both (or all three) values are checked to see if the CRC is
ok.  For those items where the CRC is ok, the counters are checked to
see which one is the latest, and that value is used.

During normal operation, another periodic routine goes over all the
eeprom checking CRCs and comparing values in redundant copies.  It
simply sets a flag if something goes wrong, and the module may report
the error for user replacement before the other locations go bad.
Depending on the project requirements it may either 1) not attempt to
to 'fix' anything or re-write anything, it merely reports on
inconsistencies it finds, or 2) if a CRC is bad, or values don't
match, it takes the latest good value and attempts a re-write of the
bad copy.  Options 2 is harder than option one, because you then have
to store more informaiton in EEPROM to limit the number of times you
attempt to re-write the data.  Further, if the EEPROM is going bad
it's often better to baby it and avoid writes, so fixing it may
actually exacerbate the problem.

This removes most problems with power down, bad eeprom cells, etc.  It
doesn't really perform EEPROM wear leveling, which is something you
must consider if you believe you're going to be doing more than 1k
writes to any given cell in the EEPROM over the life of the unit.
Even though the EEPROM is rated to 10k, 100k, or more, that's an MTBF
- statistically calculated, and any one cell can easily fail well
before then and still be withing the statistical curve of their
rating.  Wear leveling has to have a bit more thought put into it in
regards to infrequently changing values vs frequently changing values,
and whether redundant copies are actually spaced apart in EEPROM.

Simply copying the values 5 times and checking for correlation is a
very poor method for error and coherence checking. CRC for error
checking, and counters for coherence are a _significantly_ better
option.

But if you need to stick with the 5 bytes for whatever reason (perhaps
this is overkill for your situation), make sure the writes are done in
seperate operations, and space them out throughout the EEPROM if
possible.  In the PIC you mention it doesn't matter, but on other
devices if there are multiple EEPROM 'blocks' then put seperate copies
into different blocks of the EEPROM.

Also, you'll need to have a hard-coded fallback value if all the
copies fail their CRC checks, and your device is required to continue
operation (either full or partial) given complete EEPROM failure.  You
may need to do this in your scenario if three or four cells have
failed (and only 2 or no values match).

I hope this is useful.

-Adam
--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Sean Breheny :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Adam,

On Thu, Oct 29, 2009 at 8:56 AM, M. Adam Davis <stienman@...> wrote:
> On Wed, Oct 28, 2009 at 10:46 PM, Dwayne Reid <dwayner@...> wrote:
>> I recall recent discussion (and past discussions) about the problem
>> of multiple writes causing eventual read failures of static eeprom
>> values (static as in they don't change often or at all).
>
> If the data doesn't change, don't initiate an EEPROM write.  Only
> write it on change.  This should eliminate this concern.
>

Hmmm. The datasheets for many of the affected parts suggest that
rarely-changing data SHOULD be "refreshed" or re-written. Do you think
that the datasheet is mixed up here?

Sean

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Dwayne Reid :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

At 06:56 AM 10/29/2009, M. Adam Davis wrote:
>On Wed, Oct 28, 2009 at 10:46 PM, Dwayne Reid <dwayner@...> wrote:
> > I recall recent discussion (and past discussions) about the problem
> > of multiple writes causing eventual read failures of static eeprom
> > values (static as in they don't change often or at all).
>
>If the data doesn't change, don't initiate an EEPROM write.  Only
>write it on change.  This should eliminate this concern.

That used to be my standard approach.  However, Microchip is quite
adamant that frequent writes to the eeprom array will damage static
data in other locations.  In other words, data that has not been
changed or refreshed can be damaged by writes to other locations
within the eeprom array.

This is new behavior and something that I've not had to deal with previously.

You will notice that I am treating my re-writes as a refresh.  Thus,
if any of the 5 values is different from the others, I refresh all 5 bytes.

I also do NOT re-write the data if all 5 values are the same.

Power-down during writes is definite concern.  I didn't mention it
but I think that I have it covered: this particular project is
required to allow operation only while the incoming line voltage is
within a specified window.  I have a slow filter on the incoming AC
line voltage measurement routine for that purpose - and a much faster
filter that is used to disallow writes if the AC should fail.  There
is sufficient power supply reserve to allow all 5 writes to complete
should the AC fail while the writes are occurring.

Good points, though.  I appreciate it.

dwayne

--
Dwayne Reid   <dwayner@...>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
www.trinity-electronics.com
Custom Electronics Design and Manufacturing

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Gordon Williams-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I've got a 16F886 in a device where I store a number of user settable
paramaters in eeprom and I don't have any more space either in eeprom or
program memory to store multiple redundant values.

There have been a number of threads now on eeprom loss of data problems and
this has got me concerned about PIC reliability.  Is this common in all
eeproms in all PICs or are microchip's devices just crappy?

Over the life of my divice I will read the eeprom less than 700 times.  Is
this something that will cause problems?  Can someone point me to a document
were the problem is described and specs given?

Thanks,

Gordon Williams

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Isaac Marino Bavaresco :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Gordon Williams escreveu:

> I've got a 16F886 in a device where I store a number of user settable
> paramaters in eeprom and I don't have any more space either in eeprom or
> program memory to store multiple redundant values.
>
> There have been a number of threads now on eeprom loss of data problems and
> this has got me concerned about PIC reliability.  Is this common in all
> eeproms in all PICs or are microchip's devices just crappy?
>
> Over the life of my divice I will read the eeprom less than 700 times.  Is
> this something that will cause problems?  Can someone point me to a document
> were the problem is described and specs given?

Why are you worried about the number of reads the EEPROM will be
subjected? AFAIK the number of reads are unlimited, the writes are what
affect the EEPROM reliability.

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/ 
--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Dwayne Reid :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

At 11:41 AM 10/29/2009, Gordon Williams wrote:
>There have been a number of threads now on eeprom loss of data problems and
>this has got me concerned about PIC reliability.  Is this common in all
>eeproms in all PICs or are microchip's devices just crappy?
>
>Over the life of my divice I will read the eeprom less than 700 times.  Is
>this something that will cause problems?  Can someone point me to a document
>were the problem is described and specs given?

This problem appeared to surface with Microchip's later chips
(nanowatt series?).  Early chips such as the venerable F84 or the
early 16F628 don't have the problem, the (a) versions of the 16F628
(16F628A) apparently do have the problem.

So, apparently, does the 12F675.

So far as I know, reading the eeprom does NOT cause the
problems,  Instead, the problem is caused by many writes to one part
of the eeprom array.  Those bytes that are frequently written are NOT
the problem.  What does get affected is eeprom addresses that DON'T
get written.

I know that I've seen Microchip describe this in at least one data
sheet but I'll be darned if I can find just WHICH data sheet that was
(I spent 5 minutes looking just now).

I'll post the URL for the appropriate data sheet when I run across it again.

dwayne

--
Dwayne Reid   <dwayner@...>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax
www.trinity-electronics.com
Custom Electronics Design and Manufacturing

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Sean Breheny :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Thu, Oct 29, 2009 at 1:55 PM, Dwayne Reid <dwayner@...> wrote:
>
> So far as I know, reading the eeprom does NOT cause the
> problems,  Instead, the problem is caused by many writes to one part
> of the eeprom array.  Those bytes that are frequently written are NOT
> the problem.  What does get affected is eeprom addresses that DON'T
> get written.
>

Dwayne,

This seems to be in dispute. In the recent discussion on this (about 1
month ago), several people claimed that reads DO degrade the EEPROM
cell contents in these certain affected PICs. This is not mentioned in
the datasheets but people seem to claim that the information in the
datasheets is at best incomplete. I would be very happy to hear
additional information about this since we have some products out in
the field which would be severely affected by this. They use nanowatt
series parts,  continually read the EEPROM, do not store redundant
values, and write much more frequently to some parts of the array than
to others. We designed them to be compatible with products originally
made by another manufacturer so we do not have total flexibility in
the way the EEPROM is used (i.e., too much of it is used to make
duplicate copies of each value).

Sean

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Gordon Williams-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> So far as I know, reading the eeprom does NOT cause the
> problems,  Instead, the problem is caused by many writes to one part
> of the eeprom array.

Thanks for the clarification.  By "many writes" are you talking about
hundreds, tens of thousand.  The eeprom endurance is spec'ed at 1M writes.

Gordon Williams

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Re: eeprom redundant-values routines

by Gordon Williams-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maybe some clarification.

Section 10.3.1 in the 16F88x data sheet says:

10.3.1       USING THE DATA EEPROM
The   data   EEPROM   is   a   high-endurance,   byte
addressable  array  that  has  been  optimized  for  the
storage   of   frequently   changing   information   (e.g.,
program variables or other data that are updated often).
When variables in one section change frequently, while
variables in another section do not change, it is possible
to  exceed  the  total  number  of  write  cycles  to  the
EEPROM  (specification  D124)  without  exceeding  the
total   number   of   write   cycles   to   a   single   byte
(specifications  D120  and  D120A).  If  this  is  the  case,
then a refresh of the array must be performed. For this
reason,  variables  that  change  infrequently  (such  as
constants,  IDs,  calibration,  etc.)  should  be  stored  in
Flash program memory.

with 17.5 saying (sorry about the format):
Data EEPROM Memory
D120      ED Byte Endurance 100K 1M -          E/W   -40°C ? TA ? +85°C
D120A    ED Byte Endurance 10K 100K          -          E/W   +85°C ? TA ?
+125°C
D121      VDRW         VDD for Read/Write VMIN - 5.5 V      Using EECON1 to
read/write
VMIN = Minimum operating
voltage
D122      TDEW         Erase/Write Cycle Time - 5 6 ms
D123      TRETD        Characteristic Retention 40 - -          Year
Provided no other specifications
are violated
D124      TREF Number of Total Erase/Write
Cycles before Refresh(4)
1M 10M          -          E/W   -40°C ? TA ? +85°

The way that I read this was that each byte in EEPROM would last typically
1M writes (D120) and that the eeprom could have typically 10M writes (D124)
before the whole thing would need to be refreshed.

Have I got it right?

Gordon Williams



----- Original Message -----
From: "Gordon Williams" <gwilliams@...>
To: "Microcontroller discussion list - Public." <piclist@...>
Sent: Thursday, October 29, 2009 3:07 PM
Subject: Re: [PIC] eeprom redundant-values routines


>
> > So far as I know, reading the eeprom does NOT cause the
> > problems,  Instead, the problem is caused by many writes to one part
> > of the eeprom array.
>
> Thanks for the clarification.  By "many writes" are you talking about
> hundreds, tens of thousand.  The eeprom endurance is spec'ed at 1M writes.
>
> Gordon Williams
>
> --
> http://www.piclist.com PIC/SX FAQ & list archive
> View/change your membership options at
> http://mailman.mit.edu/mailman/listinfo/piclist

--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist

Parent Message unknown Re: eeprom redundant-values routines

by Bob Axtell :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Sean,

I agree that we need clarity.

If you notice, you don't need to do any "refreshing" for serial EEPROMS-
even huge ones (1M bits), so apparently the nanowatt EEPROM is a
different, (i.e. less robust), animal.

Somebody from Microchip needs to step up to the plate and CLEARLY explain
what is going on. These failures began when the nanowatt series came out,
and was not a problem before that.

--Bob


> On Thu, Oct 29, 2009 at 1:55 PM, Dwayne Reid <dwayner@...>
> wrote:
>>
>> So far as I know, reading the eeprom does NOT cause the
>> problems,  Instead, the problem is caused by many writes to one part
>> of the eeprom array.  Those bytes that are frequently written are NOT
>> the problem.  What does get affected is eeprom addresses that DON'T
>> get written.
>>
>
> Dwayne,
>
> This seems to be in dispute. In the recent discussion on this (about 1
> month ago), several people claimed that reads DO degrade the EEPROM
> cell contents in these certain affected PICs. This is not mentioned in
> the datasheets but people seem to claim that the information in the
> datasheets is at best incomplete. I would be very happy to hear
> additional information about this since we have some products out in
> the field which would be severely affected by this. They use nanowatt
> series parts,  continually read the EEPROM, do not store redundant
> values, and write much more frequently to some parts of the array than
> to others. We designed them to be compatible with products originally
> made by another manufacturer so we do not have total flexibility in
> the way the EEPROM is used (i.e., too much of it is used to make
> duplicate copies of each value).
>
> Sean
>
> --
> http://www.piclist.com PIC/SX FAQ & list archive
> View/change your membership options at
> http://mailman.mit.edu/mailman/listinfo/piclist
>


--
http://www.piclist.com PIC/SX FAQ & list archive
View/change your membership options at
http://mailman.mit.edu/mailman/listinfo/piclist