Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 19:43 16 Apr 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : uM2(+): data logging - cheap fast & easy

     Page 1 of 6    
Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 02:21am 27 Mar 2016
Copy link to clipboard 
Print this post

This one I'm pleased with

Since playing with the ESP8266 I've been interested in exploring how Serial Flash memory chips could be used for secure data logging on the Micromite as an alternative to SDcards or an external device like an Openlog.

These chips are ridiculously cheap so there is no reason not to include one on every PCB. Winbond branded chips work perfectly with the program and are recommended.





The example shown above is the one I used to develop the code and will hold 4Mbytes. Compatible chips are available from 512kbyte to 16Mbytes and the code should automatically cater for any of them.

Connections to the 8-pin chips are simple:

pin 1 (chip select) - connect to any Micromite output capable pin
pin 2 (Data out) - connect to the SPI-IN pin on the Micromite
pin 3 (write protect) - 10K resistor to 3.3V
pin 4 (GND) - connect to ground
pin 5 (Data in) - connect to the SPI-OUT pin on the Micromite
pin 6 (Clock) - connect to the SPI-CLK pin on the Micromite
pin 7 (Hold) - 10K resistor to 3.3V
pin 8 (VCC) - connect to 3.3V

The chips are a wide version of SOIC and can be easily soldered to a DIP adapter. This could then be socketed on the PCB allowing it to be swapped for reading separately in the same way as an SD card.

The intention of the coding was to hide all the workings of the chip from the user and make the user interface as simple as possible so there are just three user routines:


formatlog(chip_select_pin_number)

This routine completely erases the chip and tests it for correct erasure. In the event that the erase fails the routine will print a message and the program will end. The routine prints the ID of the chip and the size in Mbytes. It also writes to the chip an index of used pages that the logging routine uses to determine where a new record should be appended.

writelog(string-to-write, chip_select_pin_number, timestamp)

This routine appends the supplied string to the log. If the variable "timestamp" is non-zero it will automatically prepend the date and time comma-separated to the front of the string. If timestamp is 0 or not specified the string will be written as supplied. Logging strings can be constructed in the normal way using STR$ to format numbers and the "+" operator to concatenate multiple sub-strings.

readlog(chip_select_pin_number)

This routine reads the complete log and prints the contents to the console. To upload to a PC just set Teraterm (or equivalent) to record the terminal session and call readlog. The routine does not change the log data in any way so logging can be restarted after reading without any impact.

NB all of the routines are completely self-contained and can be called from the command line with no requirement for anything to have been run or set up previously - there are no global variables or constants - everything required to run is stored on the chip itself. They also obey the requirements for sharing the SPI bus with a TFT screen on the Micromite.

This means calls to the formatlog and readlog routines need never be included in the running program as they can just be called from the command line as and when required.

It really can't get any easier to include logging in any Micromite program.

The test program attached demonstrates just how easy it is to including logging commands in a program. I've tested the code using 1000, 10000, and 100000 log records. It takes 183 seconds to construct and log 10000 records.

The C-source is attached, there is nothing complicated and it was all written first in Basic and then just converted to C for improved performance.


option explicit
option default none
dim integer i
const chipselectpin=1 'chip select pin
'
' Example program to demonstrate logging to a serial flash chip
'
testdata() 'sets up the testdata generator
'
formatlog(chipselectpin) 'format the chip
'
timer=0
for i=1 to 1000 'log 1000 strings with timestamps
writelog(int2Text(i),chipselectpin,1)
next i
print "1,000 records constructed and logged in ",timer\1000," seconds"
pause 3000
'
readlog(chipselectpin) ' read back the log
'
end
'
'****************************************
'
'
sub formatlog(cspin as integer) 'erase the chip and set up the page index
local integer i,bytecount,r(2)
local s$ length 10
spi open 20000000,3,8
bytecount = getpagecount(s$,cspin)*256
print "JEDEC ID = ",s$
print "Memory size is ",bytecount\131072," Mbits"
if not (erasechip(bytecount,cspin)) then
print "erase failed"
end
endif
for i=0 to bytecount\524288
setpagewritten(i,cspin) 'mark the index pages and first real page as used
next i
spi close
print "Format complete"
end sub
'
sub writelog(s$,cspin as integer,timestamp as integer) 'write a string to the next location on the chip with optional timestamp
local integer i,x,buff(63),f,pagecount
local d$ length 10
spi open 20000000,3,8
pagecount=getpagecount(d$,cspin)
x=getnextfreepage(pagecount,cspin)
if x<>pagecount-1 then
if x<>pagecount\2048 then x=x-1 'point to the previous page to see if it has space
readpage(x,buff(0),cspin) 'read in first page
readpage(x+1,buff(32),cspin) 'read in the second page
f=getfirstfreebyte(buff())
if timestamp then
i=loadstring(date$+","+time$+","+s$,buff(),f)
else
i= loadstring(s$,buff(),f)
endif
if i>=256 then 'write the bit on the next page and set the page marker as used
writepage(x+1,buff(32),cspin)
setpagewritten(x+1,cspin)
endif
writepage(x,buff(0),cspin)
else
print "Error: Chip full"
endif
spi close
end sub
'
sub readlog(cspin as integer) 'read and print the log
local integer x,buff(63),f=0, n,i
local s$
spi open 20000000,3,8
x=getpagecount(s$,cspin)\2048 'number of indexpages
readpage(x,buff(0),cspin) 'read in first two pages
readpage(x+1,buff(32),cspin)
if buff(0) =-1 then
spi close
exit sub 'no data
endif
n=getstring(s$, buff(0),f)
print s$
do while n<>&HFF 'repeat until no more data
if f>=256 then
x=x+1
readpage(x,buff(0),cspin) 'read in next two pages
readpage(x+1,buff(32),cspin)
f=f-256
endif
n=getstring(s$, buff(0),f)
print s$
loop
spi close
end sub
'
function getnextfreepage(pagecount as integer, cspin as integer) as integer 'gets the page number of the next completely unused page
local integer i,j,r(31),p=0,found=0,indexsize=pagecount\2048
for i=0 to indexsize-1 'potentially look at all pages
readpage(i,r(),cspin)
for j=0 to 31
if r(j) then
p=j 'there must be at least one spare page if not zero
found=1
exit for
endif
next j
if found then exit for
next i
for j=0 to 63
if (r(p)>>j) and 1 then exit for
next j
getnextfreepage=i*2048+p*64+j
end function
'
sub setpagewritten(pageno as integer, cspin as integer) 'set a page as partially or completely written
local integer buff(31),i
local integer mappage=pageno\2048 'we have 2048 bits per page
local integer wordno=(pageno-mappage*2048)\64 'locate the word in the page
local integer bitno= 1<<(pageno mod 64) 'locate the bit in the word in the page
readpage(mappage,buff(),cspin)
buff(wordno) =buff(wordno) XOR bitno
writepage(mappage,buff(),cspin)
end sub
'
CFunction getpagecount 'returns the chip size in 256-byte pages and the chip ID
00000000
27BDFFD0 AFB20020 AFBF002C AFB40028 AFB30024 AFB1001C AFB00018 8CB00000
3C029D00 8C420088 00101880 00621021 8C420000 24030008 10430007 00809021
3C029D00 8C420010 02002021 24050008 0040F809 00003021 3C029D00 8C42001C
02002021 0040F809 24050005 2403009F 3C02BF80 AC435820 3C03BF80 8C625810
30420080 1040FFFD 3C02BF80 8C435820 3C03BF80 AC405820 8C625810 30420080
1040FFFD 3C02BF80 8C535820 3C03BF80 AC405820 8C625810 30420080 1040FFFD
3C02BF80 8C545820 3C03BF80 AC405820 8C625810 30420080 1040FFFD 3C119D00
8E22001C 3C03BF80 02002021 24050006 8C705820 0040F809 00000000 00133A00
24020010 AFA20010 00F43821 8E220030 00073A00 00F03821 26440001 00E03021
0040F809 00073FC3 24040006 A2440000 8FBF002C 2610FFF8 24020001 02021004
00021FC3 8FB40028 8FB30024 8FB20020 8FB1001C 8FB00018 03E00008 27BD0030
End CFunction
'
Cfunction erasechip 'size of chip in bytes, chip select pin number
00000000
27BDFFD8 AFB40020 AFBF0024 AFB3001C AFB20018 AFB10014 AFB00010 8CB30000
3C029D00 8C42001C 0080A021 24050005 0040F809 02602021 24030006 3C02BF80
AC435820 3C03BF80 8C625810 30420080 1040FFFD 3C109D00 8E02001C 3C11BF80
02602021 24050006 8E235820 0040F809 00000000 8E02001C 02602021 0040F809
24050005 240200C7 AE225820 3C03BF80 8C625810 30420080 1040FFFD 3C029D00
8C42001C 02602021 24050006 3C03BF80 8C635820 0040F809 3C119D00 3C10BF80
8E220004 0040F809 3404C350 8E22001C 02602021 0040F809 24050005 24020005
AE025820 8E025810 30420080 1040FFFD 00000000 8E025820 AE125820 8E025810
30420080 1040FFFD 00000000 8E125820 8E22001C 02602021 7C129420 0040F809
24050006 32420001 5440FFE6 8E220004 3C029D00 8C42001C 02602021 0040F809
24050005 24030003 3C02BF80 AC435820 3C03BF80 8C625810 30420080 1040FFFD
3C02BF80 8C435820 3C03BF80 AC405820 8C625810 30420080 1040FFFD 3C02BF80
8C435820 3C03BF80 AC405820 8C625810 30420080 1040FFFD 3C02BF80 8C435820
3C03BF80 AC405820 8C625810 30420080 1040FFFD 00000000 8E820004 3C03BF80
8C635820 5C400006 3C02BF80 14400014 3C029D00 8E820000 10400010 3C02BF80
AC525820 3C03BF80 8C625810 30420080 1040FFFD 3C029D00 8C42001C 02602021
24050006 3C03BF80 8C635820 0040F809 00000000 10000007 00001021 3C029D00
8C42001C 02602021 0040F809 24050006 24020001 8FBF0024 8FB40020 8FB3001C
8FB20018 8FB10014 8FB00010 03E00008 27BD0028

End Cfunction
'
CSub writepage 'page number, 256 byte data buffer, chip select pin number
00000000
27BDFFD8 AFB3001C AFB00010 AFBF0024 AFB40020 AFB20018 AFB10014 8CD30000
3C029D00 8C42001C 8C940000 00A08021 02602021 0040F809 24050005 24030006
3C02BF80 AC435820 0014A200 3C03BF80 8C625810 30420080 1040FFFD 3C119D00
8E22001C 3C12BF80 02602021 24050006 8E435820 0040F809 00000000 8E22001C
02602021 0040F809 24050005 24020002 AE425820 3C03BF80 8C625810 30420080
1040FFFD 3C02BF80 7E843C00 8C435820 3C03BF80 AC445820 8C625810 30420080
1040FFFD 3C02BF80 7E943A00 8C435820 3C03BF80 AC545820 8C625810 30420080
1040FFFD 3C02BF80 8C435820 3C03BF80 AC405820 8C625810 30420080 1040FFFD
3C02BF80 8C425820 00002021 3C03BF80 240500FF 02041021 80420000 AC625820
8C625810 30420080 1040FFFD 00000000 8C625820 10850003 3C029D00 1000FFF5
24840001 8C42001C 02602021 0040F809 24050006 24120100 3C119D00 3C10BF80
8E220004 0040F809 240400FA 8E22001C 02602021 0040F809 24050005 24020005
AE025820 8E025810 30420080 1040FFFD 00000000 8E025820 AE125820 8E025810
30420080 1040FFFD 00000000 8E125820 8E22001C 02602021 0040F809 24050006
32420001 5440FFE7 8E220004 8FBF0024 8FB40020 8FB3001C 8FB20018 8FB10014
8FB00010 03E00008 27BD0028
End CSub
'
CSub readpage 'page number, 256 byte data buffer, chip select pin number
00000000
27BDFFD8 AFB2001C AFB10018 AFBF0024 AFB30020 AFB00014 8CD20000 3C029D00
8C42001C 8C930000 00A08821 02402021 0040F809 24050005 24030003 3C02BF80
AC435820 00139A00 3C03BF80 8C625810 30420080 1040FFFD 3C02BF80 7E643C00
8C435820 3C03BF80 AC445820 8C625810 30420080 1040FFFD 3C02BF80 7E733A00
8C435820 3C03BF80 AC535820 8C625810 30420080 1040FFFD 3C02BF80 8C435820
3C03BF80 AC405820 8C625810 30420080 1040FFFD 3C02BF80 8C425820 00002021
3C03BF80 24050100 AC705820 8C625810 30420080 1040FFFD 00000000 8C705820
02241021 24840001 7C108420 1485FFF6 A0500000 3C029D00 8C42001C 02402021
0040F809 24050006 8FBF0024 8FB30020 8FB2001C 8FB10018 8FB00014 03E00008
27BD0028
End CSub
'
CFunction getfirstfreebyte
00000000
90830000 240200FF 00003021 10620014 00003821 90830001 1062000A 24020001
24020002 240500FF 24080100 00821821 90630000 54650006 24420001 10000002
00403021 00403021 10000005 00023FC3 5448FFF7 00821821 24060100 00003821
00C01021 03E00008 00E01821
End CFunction
'
CFunction loadstring 'copies a string into the write buffer
00000000
8CC30000 90820000 00621021 0043302A 14C0000A 24660001 00A31821 90870000
24C60001 24C5FFFF 0045282A A0670000 24840001 10A0FFF9 24630001 03E00008
00021FC3
End CFunction
'
CFunction getstring ' gets a string ferom the read buffer
00000000
8CC20000 00A21821 90690000 01224821 0122182A 5460000C 25220001 24430001
00A21021 90480000 24630001 2467FFFF 0127382A A0880000 24420001 10E0FFF9
24840001 25220001 00021FC3 ACC30004 ACC20000 00A92821 90A20001 03E00008
00001821
End CFunction
'
'****************************
' test data generation
'
'small
sub testdata
DATA "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"
DATA "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"
'tens
DATA "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"
'big
DATA "thousand", "million", "billion"
dim small(19) AS STRING length 10, tens(7) AS STRING length 10, big(2) AS STRING length 10
FOR i = 1 TO 19
READ small(i)
NEXT
FOR i = 0 TO 7
READ tens(i)
NEXT
FOR i = 0 TO 2
READ big(i)
NEXT
'
end sub
.
FUNCTION int2Text(number AS integer) as string
local num AS integer, outP AS STRING length 60, unit AS INTEGER
local tmpLng1 AS integer

IF 0 = number THEN
int2Text = "zero"
EXIT FUNCTION
END IF

num = ABS(number)

DO
tmpLng1 = num MOD 100
SELECT CASE tmpLng1
CASE 1 TO 19
outP = small(tmpLng1) + " " + outP
CASE 20 TO 99
SELECT CASE tmpLng1 MOD 10
CASE 0
outP = tens((tmpLng1 \ 10) - 2) + " " + outP
CASE ELSE
outP = tens((tmpLng1 \ 10) - 2) + "-" + small(tmpLng1 MOD 10) + " " + outP
END SELECT
END SELECT

tmpLng1 = (num MOD 1000) \ 100
IF tmpLng1 THEN
outP = small(tmpLng1) + " hundred " + outP
END IF

num = num \ 1000
IF num < 1 THEN EXIT DO

tmpLng1 = num MOD 1000
IF tmpLng1 THEN outP = big(unit) + " " + outP

unit = unit + 1
LOOP

IF number < 0 THEN outP = "negative " + outP
Do WHILE ASC(RIGHT$(outp,1))<=32
outp = LEFT$(outp,len(outp)-1)
loop
int2Text = outP
END FUNCTION
'*********************************


#define writeenable 0x06
#define pageprogram 0x02
#define readstatus1 0x05
#define readdata 0x03
#define eraseall 0xC7
#define JEDEC 0x9F
#define SPIsend(a) {int j;SPIBUF=a; while((SPISTAT & 0x80)==0); j=SPIBUF;}
#define SPIread(a) {SPIBUF=a; while((SPISTAT & 0x80)==0); a=SPIBUF;}
#define SPISTAT *(volatile unsigned int *)(0xbf805810)
#define SPIBUF *(volatile unsigned int *)(0xbf805820)

long long pagecount(char id[],long long *cspin){
int pin=*cspin,i,j,k;
if(ExtCurrentConfig[pin]!=EXT_DIG_OUT)ExtCfg(pin,EXT_DIG_OUT,0);
PinSetBit(pin,LATCLR);
SPIsend(JEDEC);
SPIread(i);
SPIread(j);
SPIread(k);
PinSetBit(pin,LATSET);
IntToStr(&id[1],i*65536+j*256+k,16);
id[0]=6;
return (1<<(k-8));
}
int erasechip(long long *size, long long *cspin){
int p,pin=*cspin;
char m;
PinSetBit(pin,LATCLR);
SPIsend(writeenable);
PinSetBit(pin,LATSET);
PinSetBit(pin,LATCLR);
SPIsend(eraseall);
PinSetBit(pin,LATSET);
do {
uSec(50000);
PinSetBit(pin,LATCLR);
SPIsend(readstatus1)
SPIread(m);
PinSetBit(pin,LATSET);
} while(m & 1);
PinSetBit(pin,LATCLR);
SPIsend(readdata);
SPIsend(0);
SPIsend(0);
SPIsend(0); //start address is zero
for(p=0;p<*size;p++){
SPIread(m);
if(m!=0xFF){
PinSetBit(pin,LATSET);
return 0;
}
}
PinSetBit(pin,LATSET);
return 1;
}

void writepage(long long *address, char d[], long long *cspin){
int k=0,add,m,pin=*cspin;
add=*address<<8; //convert page number to byte number
PinSetBit(pin,LATCLR);
SPIsend(writeenable);
PinSetBit(pin,LATSET);
PinSetBit(pin,LATCLR);
SPIsend(pageprogram);
SPIsend((add>>16) & 0xFF);
SPIsend((add>>8) & 0xFF);
SPIsend(add & 0xFF);
for(m=0;m<256;m++) {
SPIsend(d[k]);
k++;
}
PinSetBit(pin,LATSET);

do {
uSec(250);
PinSetBit(pin,LATCLR);
SPIsend(readstatus1)
SPIread(m);
PinSetBit(pin,LATSET);
} while(m & 1);

}
void readpage(long long *address, char d[], long long *cspin){
int k,add,pin=*cspin;
char m;
add=*address<<8; //convert page number to byte number
PinSetBit(pin,LATCLR);
SPIsend(readdata);
SPIsend((add>>16) & 0xFF);
SPIsend((add>>8) & 0xFF);
SPIsend(add & 0xFF);
for(k=0;k<256;k++){
SPIread(m);
d[k]=m;
}
PinSetBit(pin,LATSET);
}
long long getfirstfreebyte(unsigned char d[]){
int j=0;

if(d[0]==0xFF) return 0;
for(j=1;j<256;j++){
if(d[j]==0xFF) return j;
}
return 256;
}
long long loadstring(unsigned char s[],unsigned char b1[],long long *pos){
int k,j=0,len=s[0],start=*pos;
for(k=start;k<=start+len;k++){
b1[k]=s[j];
j++;
}
return start+len;
}
long long getstring(unsigned char s[],unsigned char b1[],long long *pos){
int k,j=0,start=*pos,len=b1[start];
for(k=start;k<=start+len;k++){
s[j]=b1[k];
j++;
}
*pos=start+len+1; //start of next string
return b1[start+len+1];
}


Edited by matherp 2016-03-28
 
robert.rozee
Guru

Joined: 31/12/2012
Location: New Zealand
Posts: 2285
Posted: 02:42am 27 Mar 2016
Copy link to clipboard 
Print this post

an excellent concept that looks extremely useful. i would love to see something similar included within the next micromite 2 firmware release.

might i suggest one more function:
a$ = readlogline(CS, i)

this would be used thus:
i = 0
do
a$ = readlogline(CS, i)
if (i>0) print a$
loop until (i=0)


calling with i=0 would initialize to the start of the flash chip. the variable i would return containing addressing information for the next line to read (could be page number and offset into page), or 0 if there is no next line to read.

with this addition, a flash chip could be used to hold data that an mmbasic program could itself make use of.


cheers,
rob :-)Edited by robert.rozee 2016-03-28
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9037
Posted: 03:08am 27 Mar 2016
Copy link to clipboard 
Print this post

Now, this is interesting.

I am going to have to have a play around with this.....

Do Serial Flash Memories not have page boundaries to worry about like EEPROM?
I note you are setting up 256 byte pages, but in theory, could you setup any page size you like, or are these kinds of memory chips set for a 256-byte page at factory?
Smoke makes things work. When the smoke gets out, it stops!
 
Chris Roper
Senior Member

Joined: 19/05/2015
Location: South Africa
Posts: 280
Posted: 03:15am 27 Mar 2016
Copy link to clipboard 
Print this post

  Grogster said   Now, this is interesting.

I am going to have to have a play around with this.....

Do Serial Flash Memories not have page boundaries to worry about like EEPROM?
I note you are setting up 256 byte pages, but in theory, could you setup any page size you like, or are these kinds of memory chips set for a 256-byte page at factory?


It has been a while since I last worked with Winbond Flash but I seem to recall it is in pages of 4K.

Cheers
Chris

http://caroper.blogspot.com/
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9037
Posted: 03:18am 27 Mar 2016
Copy link to clipboard 
Print this post

Okey dokey, thanks.

I am in the process of downloading the datasheet so I can get a better idea of this memory.
Smoke makes things work. When the smoke gets out, it stops!
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 03:20am 27 Mar 2016
Copy link to clipboard 
Print this post

  Quote  with this addition, a flash chip could be used to hold data that an mmbasic program could itself make use of.


Rob you already have everything needed to do something like this in the current code:

the function "writepage" writes a block of data to a specific page on the chip

writepage(page_number, data, chip_select_pin)

because of the way variable passing to CFunctions works "data" can be anything that adds up to 256 bytes

dim string mystring$ length 255 '1 byte length + 255 bytes of data
dim float myfloats!(63) ' 64 x 4-bytes
DIM integer myintegers%(31) '32 x 8-bytes

Likewise "readpage" can do the same thing

readpage(page_number, mystring$, chip_select_pin)
readpage(page_number, myfloat!(), chip_select_pin)
readpage(page_number, myintegers%(), chip_select_pin)

I specifically wanted to make the logging commands context free i.e. the Basic program shouldn't have to remember anything in order to use them. However, using the primitives as above you can use the flash chip for anything. If you want to use logging in addition then it is probably best to do direct access to high pages in the flash memory and then logging will continue to work from the beginning of flash. It would then be up to the Basic program to know what was in each page used in this way. Effectively readpage and writepage allow direct access to any 256-byte record. The log data can't be treated in this way as it is effectively a sequential stream so to access the 100th string you have to read the first 99 first.

readpage and writepage would just need wrapping with SPI OPEN and SPI CLOSE commands and if used by themselves the user would need to ensure chip_select_pin was set as an ouput (this is done at the moment in C by the "pagecount" comand)



 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 03:25am 27 Mar 2016
Copy link to clipboard 
Print this post

Do Serial Flash Memories not have page boundaries to worry about like EEPROM?


Yes pages for writing are on 256-byte boundaries. My code takes care of all this for you without wasting any space.

The 4K "page" is the minimum that can be erased but I only use full chip erase.

Flash memory is erased to all "1s". Writes convert the relevant 1s to 0s. So I can write the same data to a page with no effect or I can write additional data to a page that is part written by reading what was there, updating with the new data and then re-writing.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9037
Posted: 03:46am 27 Mar 2016
Copy link to clipboard 
Print this post

Lovely, thanks for that.

Datasheet for W25Q80B says on page 5 that the device is arranged as 256-byte pages.

As all the hard work has been done for us with your Cfunctions for this, I am now seriously looking at using one of these instead of the SD card to store my database for the security system - I don't need much space for that, but was using the SD card for easy editing, really.

Food for thought.


Smoke makes things work. When the smoke gets out, it stops!
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9037
Posted: 04:19am 27 Mar 2016
Copy link to clipboard 
Print this post

I see that you can buy the 8-pin DIL for 21 million dollars.....

21 mill DIL IC
Smoke makes things work. When the smoke gets out, it stops!
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1133
Posted: 05:05am 27 Mar 2016
Copy link to clipboard 
Print this post

@Peter

a very good idea! Thanks for the find and your code!
I ordered 5Pcs W25Q64FVSSIG (8MB chip) for a little more than 2 Euros.

Michael

EDIT
  Quote  I see that you can buy the 8-pin DIL for 21 million dollars.....

That must be a bargain! Edited by twofingers 2016-03-28
 
plover

Guru

Joined: 18/04/2013
Location: Australia
Posts: 302
Posted: 06:05am 27 Mar 2016
Copy link to clipboard 
Print this post


 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 06:36am 27 Mar 2016
Copy link to clipboard 
Print this post

UPDATE

I should have mentioned in the original post that the spare pad on the back of many TFT displays will take one of the 25Q series chips and, at least on the displays I've checked, is correctly wired. The only additional connection is to the F_CS chip select pin on the display.

To improve logging speed by a factor of 2 please substitute this CFunction

CFunction getnextfreepage
00000000
27BDFEC8 AFB7012C AFBF0134 AFBE0130 AFB60128 AFB50124 AFB40120 AFB3011C
AFB20118 AFB10114 AFB00110 8C820004 8C830000 000227C3 308407FF 00831821
0064B82B 02E2B821 0017BD40 00031AC2 02E3B825 1AE00049 8CB60000 0000A021
3C159D00 3C10BF80 241E0003 27B20110 24130020 8EA2001C 02C02021 0040F809
24050005 00141A00 AE1E5820 8E025810 30420080 1040FFFD 7C623C00 8E045820
AE025820 8E025810 30420080 1040FFFD 7C623A00 8E045820 AE025820 8E025810
30420080 1040FFFD 00000000 306300FF 8E025820 AE035820 8E025810 30420080
1040FFFD 00000000 8E025820 27A30010 AE115820 8E025810 30420080 1040FFFD
00000000 8E115820 7C118C20 A0710000 24630001 1472FFF6 02C02021 8EA2001C
0040F809 24050006 8FA20010 8FA30014 00431025 14400013 00002021 27A20018
24040001 8C430000 8C450004 00651825 1460000C 24420008 24840001 5493FFFA
8C430000 26940001 0297102A 5440FFC2 8EA2001C 10000003 24040100 0000A021
00002021 27A30010 000410C0 00621021 8C460000 8C450004 30C30001 14600011
00001021 24020001 00055840 240A0040 00024827 00461806 012B4804 30480020
00453807 01231825 00E8180B 30630001 54600005 0014A140 24420001 144AFFF5
00024827 0014A140 02842021 8FBF0134 00042180 00441021 00021FC3 8FBE0130
8FB7012C 8FB60128 8FB50124 8FB40120 8FB3011C 8FB20118 8FB10114 8FB00110
03E00008 27BD0138
End CFunction


for this Basic code

function getnextfreepage(pagecount as integer, cspin as integer) as integer 'gets the page number of the next completely unused page
local integer i,j,r(31),p=0,found=0,indexsize=pagecount\2048
for i=0 to indexsize-1 'potentially look at all pages
readpage(i,r(),cspin)
for j=0 to 31
if r(j) then
p=j 'there must be at least one spare page if not zero
found=1
exit for
endif
next j
if found then exit for
next i
for j=0 to 63
if (r(p)>>j) and 1 then exit for
next j
getnextfreepage=i*2048+p*64+j
end function


C source


long long getnextfreepage(long long *pagecount, long long *cspin){
long i,j,k=0,found=0,indexsize=*pagecount/2048,add,pin=*cspin ;
union ftype{
long long a[32];
char b[256];
}r;
for (i=0; i< indexsize;i++){ //potentially look at all pages
char m;
add=i<<8; //convert page number to byte number
PinSetBit(pin,LATCLR);
SPIsend(readdata);
SPIsend((add>>16) & 0xFF);
SPIsend((add>>8) & 0xFF);
SPIsend(add & 0xFF);
for(k=0;k<256;k++){
SPIread(m);
r.b[k]=m;
}
PinSetBit(pin,LATSET);
for(j=0 ;j<32;j++){
if (r.a[j]) {
k=j; //there must be at least one spare page if not zero
found=1 ;
break;
}
}
if (found) break;
}
for (j=0 ;j<64;j++) if ((r.a[k]>>j) & 1) break;
return i*2048+k*64+j ;
}



For those learning C note how the union ftype allows me to treat a 256-byte area of memory as either an array of bytes (8-bit) or an array of long longs (64-bit)Edited by matherp 2016-03-28
 
drkl

Senior Member

Joined: 18/10/2015
Location: Hungary
Posts: 102
Posted: 09:36am 27 Mar 2016
Copy link to clipboard 
Print this post

Hello,

Why not use the Microchip SST26VF032B flash? I try: JEDEC code, size ok,
write ok , but read back is nothing.

drkl
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 11:43am 27 Mar 2016
Copy link to clipboard 
Print this post

  Quote  Why not use the Microchip SST26VF032B flash? I try: JEDEC code, size ok,
write ok , but read back is nothing.


One problem is that the JEDEC ID doesn't give the flash size in the same format as Winbond. For Winbond the last part of the ID specifies the size as 2^ID2 bytes so for ID &HEF4016 &H16=4Mbyte, EF4017 = 8Mb, EF4014=1Mb etc.

The software uses this to set the size of the index.

The Microchip part sets the "size " as &H42. 2^&H42 means that the whole flash is dedicated to the index and nothing can be written.

To cater for this the full Microchip ID would have to be hardcoded in the pagecount CFunction then it might work if there is nothing else incompatible.

UPDATE

drkl

Please could you substitute this version of the CFunction in the code and see if it works with the Microchip flash

CFunction pagecount
00000000
27BDFFC8 AFB20024 AFBF0034 AFB50030 AFB4002C AFB30028 AFB10020 AFB0001C
8CB00000 3C029D00 8C420088 00101880 00621021 8C420000 24030008 10430007
00809021 3C029D00 8C420010 02002021 24050008 0040F809 00003021 3C029D00
8C42001C 02002021 0040F809 24050005 2403009F 3C02BF80 AC435820 3C03BF80
8C625810 30420080 1040FFFD 3C02BF80 8C435820 3C03BF80 AC405820 8C625810
30420080 1040FFFD 3C02BF80 8C545820 3C03BF80 AC405820 8C625810 30420080
1040FFFD 3C02BF80 8C555820 3C03BF80 AC405820 8C625810 30420080 1040FFFD
3C119D00 8E22001C 02002021 24050006 3C03BF80 8C735820 0040F809 00148200
24020010 AFA20010 02158021 8E220030 00108200 02138021 26440001 02003021
0040F809 00103FC3 24020006 A2420000 3C0200BF 24422642 24044000 1202000B
00002821 3C0200BF 24422602 12020006 2673FFF8 24020001 02629804 02602021
10000002 00132FC3 00002821 8FBF0034 00801021 00A01821 8FB50030 8FB4002C
8FB30028 8FB20024 8FB10020 8FB0001C 03E00008 27BD0038
End CFunction
Edited by matherp 2016-03-29
 
drkl

Senior Member

Joined: 18/10/2015
Location: Hungary
Posts: 102
Posted: 11:33am 28 Mar 2016
Copy link to clipboard 
Print this post

Dear Peter,

Thank you so much to deal with Microchip SST26VF032 memory.
We have prepared a Micromite practices panel:
https://shop.chipcad.hu/Welcome/Default.aspx?scenarioID=301&StockCode=SAJ790&ViewProduct=true&pid=1551#TabControl-2

and that it is such a chip.

I wrote to a chip testprogram, but there is also a specialty.
Shall be used:

CONST ULBPL=& H98 'GLOBAL UNLOCK PROTECTION BLOCK
SNDCMD (ULBPL)

before format and write.

ULBPL SOORCE: http://electronics.stackexchange.com/questions/156429/cant-seem-to-write-to-spi-flash

The amendment which was sent, the result:

> RUN
JEDEC ID = BF2642
Memory size is 32 Mbits
Format complete
1,000 records constructed and logged in 9 seconds
>
Reading is nothing (due to lack ULBPL-by my opinion)

Best regards

drkl

 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 06:10am 29 Mar 2016
Copy link to clipboard 
Print this post

Why do Microchip have to make things so difficult

Please try this version and let me know if it works.

NB for anyone using Winbond chips, stick with the original SMALLER version

CFunction pagecount
00000000
27BDFFC8 AFB30028 AFBF0034 AFB50030 AFB4002C AFB20024 AFB10020 AFB0001C
8CB00000 3C029D00 8C420088 00101880 00621021 8C420000 24030008 10430007
00809821 3C029D00 8C420010 02002021 24050008 0040F809 00003021 3C029D00
8C42001C 02002021 0040F809 24050005 2403009F 3C02BF80 AC435820 3C03BF80
8C625810 30420080 1040FFFD 3C02BF80 8C435820 3C03BF80 AC405820 8C625810
30420080 1040FFFD 3C02BF80 8C515820 3C03BF80 AC405820 8C625810 30420080
1040FFFD 3C02BF80 8C555820 3C03BF80 AC405820 8C625810 30420080 1040FFFD
3C129D00 8E42001C 3C03BF80 02002021 24050006 8C745820 0040F809 00118A00
24020010 AFA20010 02358821 8E420030 00118A00 02348821 26640001 02203021
0040F809 00113FC3 24020006 A2620000 3C0200BF 24422642 24124000 12220030
00009821 3C0200BF 24422602 1222002B 3C029D00 8C42001C 02002021 0040F809
24050005 24030006 3C02BF80 AC435820 3C03BF80 8C625810 30420080 1040FFFD
3C119D00 8E22001C 3C15BF80 02002021 24050006 8EA35820 0040F809 00000000
8E22001C 02002021 0040F809 24050005 24020098 AEA25820 3C03BF80 8C625810
30420080 1040FFFD 3C029D00 8C42001C 02002021 24050006 3C03BF80 8C635820
0040F809 2694FFF8 24020001 0282A004 02809021 10000002 00149FC3 00009821
8FBF0034 02401021 02601821 8FB50030 8FB4002C 8FB30028 8FB20024 8FB10020
8FB0001C 03E00008 27BD0038
End CFunction
 
drkl

Senior Member

Joined: 18/10/2015
Location: Hungary
Posts: 102
Posted: 08:05am 29 Mar 2016
Copy link to clipboard 
Print this post

Hello Peter,

It operates!!!

Many, many thanks for you.
You are an always helpful, (and very clever) man.

drkl







 
paceman
Guru

Joined: 07/10/2011
Location: Australia
Posts: 1323
Posted: 12:59am 06 Apr 2016
Copy link to clipboard 
Print this post

  matherp said   I should have mentioned in the original post that the spare pad on the back of many TFT displays will take one of the 25Q series chips and, at least on the displays I've checked, is correctly wired. The only additional connection is to the F_CS chip select pin on the display.

Peter, would putting a 25Q on these panels then allow an "in-built" touch calibration to be made permanently available, say on page 1, rather than having to re-calibrate when e.g. firmware is updated, libraries erased, processors changed etc.

Greg
 
panky

Guru

Joined: 02/10/2012
Location: Australia
Posts: 1094
Posted: 02:28pm 06 Apr 2016
Copy link to clipboard 
Print this post

Peter,

Could you expand a little more on using the 25Q chip please? My 7" display has an unoccupied chip position labelled U2 adjacent to the SD card connector - is that what you are referring to?

Cheers,
Doug.

... almost all of the Maximites, the MicromMites, the MM Extremes, the ArmMites, the PicoMite and loving it!
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8563
Posted: 10:17pm 06 Apr 2016
Copy link to clipboard 
Print this post

  Quote  My 7" display has an unoccupied chip position labelled U2 adjacent to the SD card connector - is that what you are referring to?


Yes - just solder the 25Q onto those pads and connect the Micromite to the F_CS pin to use as the chip se3lect
 
     Page 1 of 6    
Print this page
© JAQ Software 2024