Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 03:18 04 Aug 2025 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 : V4.7 : MX170 SDCard FAT32 Driver

     Page 1 of 3    
Author Message
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 09:40am 10 Aug 2015
Copy link to clipboard 
Print this post

Hi

I have created a driver which enables the PIC32MX170 28/44pin Micromite to Read/Write files from/to a FAT32 formatted SDCard.

One of the primary uses for this FAT32 driver is to enable MMBasic programs to perform logging operations and then for a PC/Tablet/MAC to be able to read the logfile and process it using common tools such as Excel/Libre Calc/OpenOffice Calc, ie the files produced are 100% FAT32 compliant. NB there is nothing limiting the use of the driver to just logging applications, but most embedded systems need logging capability hence the chosen example MMBasic program.

Once installed, the Driver's memory footprint is
> memory
Flash:
23K (39%) Program (441 lines)
7K (12%) 1 CFunction
29K (49%) Free

RAM:
2K ( 3%) 11 Variables
0K ( 0%) General
51K (97%) Free
>


Only 7K !!

The hardware required is
1) PIC32MX170 28/44 pin Micromite loaded with MmBasic 4.7 B23 or later
'PIC32MX170 28 Pin wiring
'Pin 2 Chip Select can be any digital output pin
'Pin 3 MOSI
'Pin 14 MISO
'Pin 25 SCLK

2) SPI SDCard adapter, eg Catalex http://www.dx.com/p/spi-microsd-card-adapter-v0-9b-for-arduino-works-with-official-arduino-board-246784#.Vcj0F_mrTRY or http://www.ebay.co.uk/itm/Micro-SD-Storage-Board-Mciro-SD-TF-Card-Memory-Shield-Module-SPI-For-Arduino-New-/251820477428 ?hash=item3aa1ab8bf4

The software 2015-08-10_185905_SDCardDriverExample.zip and you will also need the blank logfile.csv 2015-08-10_185941_logfile.zip The logfile.csv is 10 MBytes but when empty compresses down to 11KBytes.

How to use
1) Unzip logfile.zip and copy logfile.csv to the root of your uSD card, and insert it into your SPI uSD card adaprer.

2) Unzip SDCardDriverExample and load into your Micromite

3) Run the program several times

4) The program should display something similar to
> Run
Test Harness for CFunction FAT32 FileSystem driver (c) Peter Carnegie 2015 Ver 1.5
Simulates use of SDCard for Logging data
CFunction Driver Version= 1.5
Initialise the Driver
Initialise the disk
Mount the disk
Open File /logfile.csv
Get Length of file /logfile.csv
File /logfile.csv is 10485760 bytes in size
Get Number of logging records already in file
Number of Existing Log Records : 0
Write Updated Number of Records to disk
Flush data to secure it
Create Header entry if it doesn't exist
Write a simulated Temperature entry to the Log file
Write New Log record out :"10-08-2015","19:01:16","20.32"
Flush log record to secure it

Read and display our logging file
Num Records = 5
Header = Log File Started at 10-08-2015 19:01:03
Record 1 = "10-08-2015","19:01:04","20.86"
Record 2 = "10-08-2015","19:01:09","20.58"
Record 3 = "10-08-2015","19:01:11","20.71"
Record 4 = "10-08-2015","19:01:14","20.29"
Record 5 = "10-08-2015","19:01:16","20.32"

Close File

Close Driver
>

The records are in Comma Separated Value format.

5)Now take the uSDCard and insert it into your PC's card reader and open logfile.csv in your spreadsheet, eg Excel. You should find that logfile.csv will load straight in without any problems.

(6)Reinsert the SDCard back into the Micromite setup and run the program a few times to generate some more simulated logging records, proving that the program is truly appending persistent records to the SDCard.

This driver has been created with minimal memory impact in mind, targeted at Embedded Systems, so it it doesn't support operations like DIR, DEL, CREATE File and so on. I will release a driver which does provide the full range of support expected from a file system driver in due course.

I have provided thin MMBasic wrapper functions around the calls to the CFunction driver, and of course if memory is really, really tight, then user code can of course directly call the CFunction entry point.

Some of the limitations of this driver are

1) File size is limited to 4GBytes
2) Files cannot be created or extended, so you MUST create a large blank, ie zero-filled, file into which all subsequent write operations will take place
3) The seek command must seek on 512 byte boundaries, so with a 4GByte file that limits the maximum number of logging records to 8,388,600 before a second 4GByte file needs to be used.
4) The driver is designed for 40/48MHz operation - I will release a version which can deal with different CPU speeds in due course.
5) The driver is limited to FAT32, ie FAT12/16 are NOT supported
6) Filenames MUST be in 8.3 format

This driver is hot off the keyboard so please treat it as a Beta.

I couldn't have written the FAT32 driver without publications by ChaN.

I hope someone finds this driver useful - all feedback most gratefully received.

Peter

OPTION EXPLICIT
OPTION DEFAULT NONE
CPU 48

CONST VER!=1.6

'Using Catalex micro SDCard breakout board
'PIC32MX170 28 Pin wiring
'Pin 2 Chip Select can be any digital output pin
'Pin 3 MOSI
'Pin 14 MISO
'Pin 25 SCLK

PRINT "Test Harness for CFunction FAT32 FileSystem driver (c) Peter Carnegie 2015 Ver";Ver!
PRINT "Simulates use of SDCard for Logging data"

'Useful loop variable
DIM I%=0

'We're using pin 2 for Chip Select
CONST CSPin%=2

'Used for holding filename
'Use dd if=/dev/zero of=logfile.csv bs=1M count=10 to make a blank logfile
DIM FileName$="/logfile.csv"

'Used for byte I/O buffer
DIM Buffer$=STRING$(255," ")

'Offset in file of where to start Reading/Writing From/To
DIM Offset%=0

'Captures number of Bytes READ/WRITTEN
DIM ByteCount%=0

'Used to capture the return values from functions
DIM Result%=-1

'Used for calculating Number of Log Records
DIM NumRecords%

'Appended to each line in the file
CONST CRLF$=CHR$(13)+CHR$(10)

'Quote Character for CSV format
CONST Quot$=CHR$(34)

PRINT "CFunction Driver Version=";File.Ver()

PRINT "Initialise the Driver"
Result%=File.Driver.Init(CSPin%)
PError "Failed to Initialise DRIVER. Please Power Cycle system",Result%,1

PRINT "Initialise the disk"
Result%=File.Disk.Init()
PError "Failed to Initialise Disk. Please re-insert media and try again",Result%,1

PRINT "Mount the disk"
Result%=File.Mount.Disk()
PError "Failed to Mount Disk. Please re-insert media and try again",Result%,1

PRINT "Open File ";FileName$
Result%=File.Open(FileName$)
PError "Failed to Open file "+FileName$,Result%,1

PRINT "Get Length of file ";FileName$
Result%=File.Length(ByteCount%)
PError "Failed to get length of "+FileName$,Result%,1
PRINT "File ";FileName$;" is ";ByteCount%;" bytes in size"

PRINT "Get Number of logging records already in file"
Buffer$=STRING$(128," ")
Offset%=0
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Read the first 128 bytes
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read file",Result%,0

'Get number of existing log records
IF INSTR(Buffer$,".0")>0 THEN
NumRecords%=VAL(MID$(Buffer$,1,INSTR(Buffer$,".0")-1))
ELSE
NumRecords%=0
ENDIF
PRINT "Number of Existing Log Records :";I%

'Update the number of records we've written out to disk
'Increment the number of records because we're going to
'append a new one
NumRecords%=NumRecords%+1
Buffer$=STR$(NumRecords%)+ ".0" +CRLF$

'Now write it back out to disk
Offset%=0
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

PRINT "Write Updated Number of Records to disk"
ByteCount%=0
Result%=File.Write(Buffer$,ByteCount%)
PError "Failed to write to file",Result%,0

PRINT "Flush data to secure it"
Result%=File.Flush()
PError "Flush to disk failed",Result%,0

PRINT "Create Header entry if it doesn't exist"
Offset%=512
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Read the Header block
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read file",Result%,0

'Header exists ?
IF INSTR(1,Buffer$,"Log File")<1 THEN

PRINT "Creating File Header"

Offset%=512
PRINT "Seek to ";Offset%

Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

Buffer$="Log File Started at "+DATE$+" "+TIME$+CRLF$
Result%=File.Write(Buffer$,ByteCount%)
PError "Failed to write to file",Result%,0

Result%=File.Flush()
PError "Flush to disk failed",Result%,0

ENDIF

PRINT "Write a simulated Temperature entry to the Log file"
Offset%=1024+(NumRecords% * 512)
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Simulate temperature logging
Buffer$=Quot$+DATE$+Quot$+","+Quot$+TIME$+Quot$+","+Quot$+STR$(20 + RND(1),2,2)+Quot$+CRLF$
PRINT "Write New Log record out :";Buffer$;
Result%=File.Write(Buffer$,ByteCount%)
PError "Failed to write to file",Result%,0

PRINT "Flush log record to secure it"
Result%=File.Flush()
PError "Failed to Flush data to disk. Error Code:",Result%,0

PRINT
PRINT "Read and display our logging file"
Buffer$=STRING$(128," ")
Offset%=0
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Get Number of Log records
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read File ",Result%,0

'Allow for 10 million records
NumRecords%=VAL(MID$(Buffer$,1,INSTR(Buffer$,".0")-1))
PRINT "Num Records = ";STR$(NumRecords%)

'Get Header
Offset%=512
Result%=File.Seek(Offset%)

Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read File ",Result%,0
PRINT "Header = ";Buffer$;

'Seek to start of logging records
Offset%=1024
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Display each Log Record
FOR I%=1 TO NumRecords%
Offset%=1024 + I%*512
Result%=File.Seek(Offset%)
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read File ",Result%,0
PRINT "Record";STR$(I%,7);" = ";Buffer$;
NEXT I%

PRINT
PRINT "Close File"
Result%=File.Close()
PError "Failed to Close File",Result%,0

PRINT "Close Driver"
Result%=File.Driver.Close()
PError "Failed to Close Driver",Result%,0
IF Result%<>0 THEN
PRINT "Please issue CPU Restart command at MMBasic command prompt"
ENDIF

END

'*************************************************
'
' Print Error Message if Code% is NON-Zero
' END if Hard% is NON-Zero
'
'
SUB PError(Msg$,Code%,Hard%)
IF Code%=0 THEN EXIT SUB
PRINT "Error : ";Msg$;". Error Code:";Code% AND &Hff
IF Hard%<>0 THEN END
END SUB


'***********************************************
'
' CUNCTION FAT Filesystem Driver
'
' (c) Copyright Peter Carnegie 2015
'
' File.Driver.Init Initialise the Driver
' File.Driver.Close Close the Driver and release all resources
' File.Disk.Init Initialise the Disk Sub-System
' File.Disk.Mount Mount the disk into the filesystem
' File.Open Open File
' File.Close Close File
' File.Read Read from File
' File.Write Write to File
' File.Flush Flush bytes to disk
' File.Seek Move READ/WRITE pointer to position
' File.Ver Return Driver Version
' File.Length Returns length of File in Bytes
'
' The CFunction can of course be called directly from user code
' These MMBasic wrapper functions just make things neater and tidier !
'
'
'***********************************************


'***********************************************
'
' Initialise the FAT FileSystem Device Driver
'
' CSPinNum% is the pin number used for CS (Chip Select)
'
' Returns the address of the persistent driver memory
'
'
FUNCTION File.Driver.Init(CSPinNum%) AS INTEGER

'Get address of the CFunction Driver itself
LOCAL AddrOfSDCard%=PEEK(CFUNADDR Driver.SDCard)

LOCAL Addr%

LOCAL Result%=Driver.SDCard(0,AddrOfSDCard%,CSPinNum%,Addr%)

File.Driver.Init=Result%

END FUNCTION


'***********************************************
'
' Initialise the Disk
'
' Returns 0 if Successful
'
'
FUNCTION File.Disk.Init() AS INTEGER

LOCAL Result%=Driver.SDCard(1)
File.Disk.Init=Result%

END FUNCTION


'***********************************************
'
' Mount the disk
'
' Returns 0 if succesful else non-zero
'
'
FUNCTION File.Mount.Disk() AS INTEGER

LOCAL Result%=Driver.SDCard(2)
File.Mount.Disk=Result%

END FUNCTION


'***********************************************
'
' Open File
'
' Returns 0 if succesful else non-zero
'
'
FUNCTION File.Open(Path$) AS INTEGER

LOCAL Result%=Driver.SDCard(3,Path$)
File.Open=Result%

END FUNCTION


'***********************************************
'
' Read File - Sequential
'
' Returns 0 if succesful else non-zero
' On Entry
'
' On Exit
' Buffer$ will contain the bytes read in from disk
' NumBytes% will contain the number of bytes actually read
' If NumBytes%=0 then End Of File has been reached
'
' Use File.Seek to position the write pointer
'
FUNCTION File.Read(Buffer$, NumBytes%) AS INTEGER

LOCAL Result%=Driver.SDCard(4,Buffer$,NumBytes%)
File.Read=Result%

END FUNCTION


'***********************************************
'
' Write File - Sequential
'
' Returns 0 if succesful else non-zero
' On Entry
' Buffer$ contains the bytes to be written
'
' On Exit
' NumBytes% will contain the number of bytes actually written
'
' Use File.Seek to position the write pointer
'
FUNCTION File.Write(Buffer$,NumBytes%) AS INTEGER

NumBytes%=-1

LOCAL Result%=Driver.SDCard(5,Buffer$,NumBytes%)
File.Write=Result%

END FUNCTION


'***********************************************
'
' Flush Data to disk
'
' Returns 0 if succesful else non-zero
'
'
FUNCTION File.Flush() AS INTEGER

LOCAL Buffer$=""
LOCAL Offset%=0
LOCAL BytesWritten%=-1

LOCAL Result%=Driver.SDCard(5,Buffer$,BytesWritten%)
File.Flush=Result%

END FUNCTION


'***********************************************
'
' Close File
'
' Returns 0 if succesful else non-zero
' Flushes any unwritten bytes to the physical disk
'
'
FUNCTION File.Close() AS INTEGER

LOCAL Result%=Driver.SDCard(6)
File.Close=Result%

END FUNCTION


'***********************************************
'
' Drive Close
'
' Returns 0 if succesful else non-zero
' Unconfigures SPI
' Unconfigures CS pin
' FREEs up persistent RAM
'
'
FUNCTION File.Driver.Close() AS INTEGER

LOCAL Result%=0
Result%=Driver.SDCard(7)
File.Driver.Close=Result%

END FUNCTION


'***********************************************
'
' File Seek
'
' Returns 0 if succesful else non-zero
' Moves Reading/Writing offset to Position%
'
'
FUNCTION File.Seek(Position%) AS INTEGER

LOCAL Result%=Driver.SDCard(8,Position%)
File.Seek=Result%

END FUNCTION


'***********************************************
'
' Driver Version
'
' Returns Driver Version as a FLOAT, eg 1.5
'
'
FUNCTION File.Ver() AS FLOAT

LOCAL Result%=Driver.SDCard(9)
File.Ver=Result% / 100

END FUNCTION


'***********************************************
'
' Length of File
'
' Returns Length of File in Length%
' Returns 0 if OK, non-zero otherwise
'
'
FUNCTION File.Length(Length%) AS INTEGER

LOCAL Result%=Driver.SDCard(10,Length%)
File.Length=Result%

END FUNCTION


'******************************************************************************
'Created : 2015-08-10 15:20:23 UTC
'Author : Peter Carnegie
'Generator : CFuncGen Ver 2.1.5.0
'
CFUNCTION Driver.SDCard
00000686
10c00006 00801021 00862021 a0450000 24420001 5444fffe a0450000 03e00008
00000000
2407ffff 24c6ffff 10c70008 00001021 80830000 80a20000 00621023 14400003
24840001 1000fff7 24a50001 03e00008 00000000
27bdffe0 afbf001c 3c029d00 8c42008c 8c420000 2c830002 1460001e 8c42005c
8c430014 0083182b 1060001c 24030003 8c450000 14a3001e 000429c2 8c420018
3086007f 27a40010 00a22821 00063080 24070004 04110563 00000000 14400010
24030001 93a30013 00031e00 93a20012 00021400 00621825 93a20010 00621825
93a20011 00021200 00621825 10000004 7c63d800 10000002 24030001 24030001
00601021 8fbf001c 03e00008 27bd0020 1000ffff 00000000
3c029d00 8c42008c 8c420000 8c43005c 2484fffe 8c650014 24a5fffe 0085282b
10a00005 00001021 8c650008 8c620020 70851802 00621021 03e00008 00000000
90830015 00031a00 90820014 00621825 00031c00 9082001b 00021200 9084001a
00441025 03e00008 00621025
27bdffe8 afbf0014 afb00010 00808021 3c029d00 8c42008c 8c420000 8c43005c
ac800000 8c840008 24050001 1085000c 24020001 8c650014 0085282b 10a00009
8fbf0014 50800001 8c64001c ae04000c 0411FFD0 00000000 ae020010 00001021
8fbf0014 8fb00010 03e00008 27bd0018
27bdffe0 afbf001c afb20018 afb10014 afb00010 00808021 3c029d00 8c42008c
8c420000 8c52005c 8c910000 26310001 3231ffff 12200027 24020003 8c830010
50600025 8fbf001c 3222000f 54400020 ae110000 24630001 ac830010 8c84000c
14800007 00111902 8e430010 0223182b 14600016 24020003 10000017 8fbf001c
8e420008 2442ffff 00621024 54400010 ae110000 0411FF75 00000000 00402021
2c430002 1460000b 24020001 8e430014 0083182b 10600007 24020003 ae04000c
0411FF98 00000000 ae020010 ae110000 00001021 8fbf001c 8fb20018 8fb10014
8fb00010 03e00008 27bd0020
27bdffe0 afbf001c afb20018 afb10014 afb00010 00808821 00a09021 0411FFA1
00000000 14400020 00408021 8e260000 30c6000f 02402021 8e250010 00063140
24070020 041104C7 00000000 0002802b 16000016 02001021 92420000 50400012
24100003 9242000b 30420008 14400008 02202021 02402021 8e250004 2406000b
0411FF32 00000000 10400007 02202021 0411FFA0 00000000 1040ffe4 00408021
10000002 02001021 02001021 8fbf001c 8fb20018 8fb10014 8fb00010 03e00008
27bd0020
27bdffe0 afbf001c afb20018 afb10014 afb00010 00a08021 3c029d00 8c42008c
8c520000 8c910004 02202021 24050020 2406000b 0411FF0B 00000000 8e090000
00002021 00001821 24080008 240a002f 2407002e 240b0008 01231021 80450000
30a200ff 24630001 2c460021 14c0001e 306300ff 504a001d 01231821 10470003
0088302b 14c00008 00000000 550b0017 01231821 54470015 01231821 01602021
1000ffed 2408000b 04a10005 2445ff9f 8e450044 00a21021 9042ff80 2445ff9f
30a500ff 2ca5001a 10a00003 02242821 2442ffe0 304200ff a0a20000 24840001
1000ffdd 308400ff 01231821 ae030000 2c420021 a222000b 00001021 8fbf001c
8fb20018 8fb10014 8fb00010 03e00008 27bd0020
27bdffe0 afbf001c afb10018 afb00014 00808021 afa60028 80c20000 24030020
14430006 00a08821 24c60001 afa60028 80c20000 5043fffd 24c60001 2403002f
54430004 ae000008 24c60001 afa60028 ae000008 8fa20028 90420000 2c420020
10400006 02002021 0411FF18 00000000 10000019 a2200000 02002021 27a50028
0411FF9A 00000000 14400013 02002021 02202821 0411FF64 00000000 1440000f
8fbf001c 8e030004 9063000b 5460000c 8fb10018 9222000b 30420010 10400005
02202021 0411FEF6 00000000 1000ffea ae020008 24020003 8fbf001c 8fb10018
8fb00014 03e00008 27bd0020
27bdffe0 afbf001c afb10018 afb00014 00808021 00a08821 240601fe 24070002
0411041F 00000000 14400018 24030003 92040001 00042200 92020000 00822025
7c042620 2402aa55 14820010 24030002 02002021 02202821 24060052 24070002
0411040F 00000000 14400008 24030001 92030001 00031a00 92020000 00621825
7c031e20 38634146 0003182b 00601021 8fbf001c 8fb10018 8fb00014 03e00008
27bd0020
27bdffb8 afbf0044 afb20040 afb1003c afb00038 00808821 3c029d00 8c42008c
8c500000 ae00005c 04110363 00000000 30420001 1440006a 24030002 27a40010
00002821 0411FFC5 00000000 24030001 1443001a 00009021 27a40010 00002821
240601be 24070010 041103E4 00000000 1440005b 24030001 93a20014 10400058
24030006 93b2001b 00129600 93a2001a 00021400 02429025 93a20018 02429025
93a20019 00021200 02429025 27a40010 02402821 0411FFA9 00000000 24040003
10440047 24030001 14400045 24030006 27a40010 02402821 2406000d 24070024
041103C6 00000000 1440003d 24030001 93a2001a 00021200 93a30019 00431025
1440000c 93a30013 93a3002a 00031e00 93a20029 00021400 00621025 93a30027
00431025 93a30028 00031a00 00431025 93a30013 70431002 93a60012 00063200
93a30011 00c33025 02469021 ae320018 93a50010 ae250008 93a30015 00031a00
93a40014 00641825 ae230010 93a40017 00042200 93a70016 00872025 1480000b
00031902 93a70026 00073e00 93a40025 00042400 00e42025 93a70023 00872025
93a70024 00073a00 00872025 00862023 00822023 00832023 0085001b 00a001f4
00002812 24a50002 ae250014 3404fff7 00a4282b 10a00009 24040003 24030006
00601021 8fbf0044 8fb20040 8fb1003c 8fb00038 03e00008 27bd0048 ae240000
93a50032 00052e00 93a40031 00042400 00a42025 93a5002f 00852025 93a50030
00052a00 00852025 ae24001c 02439021 02421021 ae220020 ae200004 ae11005c
1000ffe7 00001821
27bdffa0 afbf005c afb10058 afb00054 00803021 3c029d00 8c42008c 8c420000
8c51005c ae200004 27a20024 afa20014 27a40010 27a50030 0411FEFB 00000000
1440001b 00408021 93a20030 10400017 93a2003b 30420010 54400015 24100003
27a40030 0411FE18 00000000 ae22002c 93a3004f 00031e00 93a2004e 00021400
00621025 93a3004c 00431025 93a3004d 00031a00 00431025 ae220028 ae200024
24020001 10000002 ae220004 24100003 02001021 8fbf005c 8fb10058 8fb00054
03e00008 27bd0060
27bdffd0 afbf002c afb60028 afb50024 afb40020 afb3001c afb20018 afb10014
afb00010 0080a821 00c09821 3c029d00 8c42008c 8c420000 8c50005c acc00000
12000049 24020005 8e030004 30630001 10600045 24020004 8e120028 8e020024
02429023 0245102b 00a2900a 1240003e 00001021 0080a021 24160200 8e020024
304301ff 5460001e 8e060024 8e110008 2631ffff 00021a42 02238824 323100ff
5620000e 8e040030 54400003 8e040030 10000003 8e02002c 0411FD93 00000000
2c430002 50600004 ae020030 ae000004 10000025 24020001 8e040030 0411FDB8
00000000 14400004 00518821 ae000004 1000001d 24020001 ae110034 8e060024
30c601ff 02c61023 0052882b 0251100a 00408821 00002021 0295200b 8e050034
00403821 041102F1 00000000 50400004 8e020024 ae000004 1000000b 24020001
00511021 ae020024 02519023 8e620000 00511021 12400003 ae620000 1000ffc7
0291a021 00001021 8fbf002c 8fb60028 8fb50024 8fb40020 8fb3001c 8fb20018
8fb10014 8fb00010 03e00008 27bd0030
27bdffd0 afbf002c afb60028 afb50024 afb40020 afb3001c afb20018 afb10014
afb00010 00a09021 00c09821 0080a021 3c029d00 8c42008c 8c420000 8c50005c
acc00000 12000077 24020005 8e030004 30640001 10800073 24020004 14a00011
30630040 5060000a 8e030004 00002021 00002821 04110307 00000000 50400004
8e030004 ae000004 10000066 24020001 2402ffbf 00621024 ae020004 10000061
00001021 54600006 8e030028 8e030024 2402fe00 00621024 ae020024 8e030028
8e020024 00621023 0052182b 10600004 24150200 10400053 00409021 24150200
2416ffbf 8e020024 304301ff 54600028 8e110024 8e110008 2631ffff 00021a42
02238824 323100ff 5620000e 8e040030 54400003 8e040030 10000003 8e02002c
0411FD15 00000000 2c430002 50600004 ae020030 ae000004 1000003a 24020001
8e040030 0411FD3A 00000000 14400004 00512821 ae000004 10000032 24020001
ae050034 00002021 041102CA 00000000 50400004 8e020004 ae000004 10000029
24020001 34420040 ae020004 8e110024 323101ff 02b18823 0232102b 0242880a
02802021 02202821 041102BA 00000000 50400004 8e020024 ae000004 10000019
24020001 00511021 ae020024 8e620000 00511021 ae620000 8e020024 304201ff
5440000d 02519023 00002021 00002821 041102A8 00000000 50400004 8e020004
ae000004 10000007 24020001 00561024 ae020004 02519023 1640ffb2 0291a021
00001021 8fbf002c 8fb60028 8fb50024 8fb40020 8fb3001c 8fb20018 8fb10014
8fb00010 03e00008 27bd0030
27bdffe0 afbf001c afb00018 3c029d00 8c42008c 8c500000 00002021 00002821
27a60010 0411FF63 00000000 ae00005c 8fbf001c 8fb00018 03e00008 27bd0020
27bdffd8 afbf0024 afb30020 afb2001c afb10018 afb00014 3c029d00 8c42008c
8c420000 8c50005c 1200004d 24020005 8e030004 30630001 10600049 24020004
8e020028 0044902b 0092100a 00409021 8e030024 ae000024 12400041 00001021
8e110008 10600012 00118a40 2463ffff 2642ffff 0051001b 022001f4 00001012
0071001b 022001f4 00002012 0044102b 54400008 8e04002c 00111023 00431824
ae030024 02439023 10000003 8e040030 8e04002c ae040030 0232102b 10400017
00119823 02519023 0411FC88 00000000 00402021 2c420002 54400006 ae000004
8e020014 0082102b 54400004 ae040030 ae000004 1000001a 24020001 8e020024
00511021 ae020024 02531021 00511821 0223182b 5460ffec 00409021 8e020024
00529021 ae120024 0411FC9E 00000000 54400004 8e040008 ae000004 10000008
24020001 2484ffff 8e030024 00031a42 00831824 00431021 ae020034 00001021
8fbf0024 8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0028
00052840 0085001b 00a001f4 00001012 03e00008 2442ffff
27bdffe0 afbf001c afb10018 afb00014 3c029d00 8c43008c 8c710000 8c420010
3c03bf81 8c65f220 7ca5d800 3c030661 24630053 10a3000b 24040003 3c03bf81
8c64f220 7c84d800 3c030660 24630053 00832026 24030003 24050014 00a4180b
00602021 24050008 0040f809 00003021 3c029d00 8c420010 3c03bf81 8c65f220
7ca5d800 3c030661 24630053 10a3000b 2404000e 3c03bf81 8c64f220 7c84d800
3c030660 24630053 00832026 2403000e 24050029 00a4180b 00602021 24050002
0040f809 00003021 3c029d00 8c420010 3c03bf81 8c65f220 7ca5d800 3c030661
24630053 10a3000b 24040019 3c03bf81 8c64f220 7c84d800 3c030660 24630053
00832026 24030019 2405000e 00a4180b 00602021 24050008 0040f809 00003021
3c02bf81 ac40f230 3c05aa99 24a56655 ac45f230 3c045566 348499aa ac44f230
3c03bf81 8c66f200 7c066b44 ac66f200 3c06bf81 8cc7fa84 24100001 7e071804
acc7fa84 3c06bf81 8cc7fb04 24080003 7d071804 acc7fb04 ac40f230 ac45f230
ac44f230 8c62f200 7e026b44 ac62f200 34038120 3c02bf80 ac435800 3c029d00
8c420000 8c440000 3c050003 34a5d090 0411FF8D 00000000 3c03bf80 ac625830
ae300038 8fbf001c 8fb10018 8fb00014 03e00008 27bd0020
27bdffe8 afbf0014 afb00010 3c029d00 8c43008c 8c700000 8c420010 3c03bf81
8c65f220 7ca5d800 3c030661 24630053 10a3000b 24040003 3c03bf81 8c64f220
7c84d800 3c030660 24630053 00832026 24030003 24050014 00a4180b 00602021
00002821 0040f809 00003021 3c029d00 8c420010 3c03bf81 8c65f220 7ca5d800
3c030661 24630053 10a3000b 2404000e 3c03bf81 8c64f220 7c84d800 3c030660
24630053 00832026 2403000e 24050029 00a4180b 00602021 00002821 0040f809
00003021 3c029d00 8c420010 3c03bf81 8c65f220 7ca5d800 3c030661 24630053
10a3000b 24040019 3c03bf81 8c64f220 7c84d800 3c030660 24630053 00832026
24030019 2405000e 00a4180b 00602021 00002821 0040f809 00003021 3c02bf81
ac40f230 3c05aa99 24a56655 ac45f230 3c045566 348499aa ac44f230 3c03bf81
8c66f200 7c066b44 ac66f200 3c06bf81 8cc7fb04 7c071804 acc7fb04 ac40f230
ac45f230 ac44f230 8c62f200 24040001 7c826b44 ac62f200 ae000038 8fbf0014
8fb00010 03e00008 27bd0018
27bdffe8 afbf0014 3c029d00 8c420004 0040f809 24040064 8fbf0014 03e00008
27bd0018
308400ff 3c02bf80 ac445820 3c03bf80 8c625810 30420001 1040fffd 3c02bf80
8c425820 03e00008 00000000
240300ff 3c02bf80 ac435820 3c03bf80 8c625810 30420001 1040fffd 3c02bf80
8c425820 03e00008 304200ff
27bdffe0 afbf001c afb20018 afb10014 afb00010 309100ff 3c029d00 8c42008c
8c500000 7c111420 04410009 00a09021 24040077 00002821 0411FFF1 00000000
2c430002 1060002f 8fbf001c 3231007f 8e020054 8e030050 ac430000 0411FFDD
00000000 8e020058 8e030050 ac430000 0411FFD8 00000000 02202021 0411FFCA
00000000 00122602 0411FFC7 00000000 7e443c00 0411FFC4 00000000 7e443a00
0411FFC1 00000000 324400ff 0411FFBE 00000000 24020040 12220006 24040095
3a310048 24020001 24030087 00402021 0071200a 0411FFB4 00000000 2410000a
0411FFBC 00000000 7c021c20 04610004 2610ffff 321000ff 1600fff9 00000000
8fbf001c 8fb20018 8fb10014 8fb00010 03e00008 27bd0020
27bdffd0 afbf002c afb40028 afb30024 afb20020 afb1001c afb00018 3c029d00
8c42008c 8c510000 0411FEB7 00000000 8e220054 8e230050 ac430000 2410000a
0411FF9E 00000000 2610ffff 321000ff 1600fffb 24040040 00002821 0411FFA2
00000000 24030001 1443005a 00009021 24040048 240501aa 0411FF9B 00000000
24030001 14430033 240400e9 27b40010 27b30014 02808021 0411FF88 00000000
a2020000 26100001 1613fffb 93a30012 24020001 14620047 00009021 93a30013
240200aa 54620044 a2320048 10000007 24102710 0411FF65 00000000 16000004
240400e9 10000039 00009021 240400e9 3c054000 0411FF7C 00000000 5440fff5
2610ffff 12000033 00009021 2404007a 00002821 0411FF74 00000000 5440002e
a2320048 0411FF65 00000000 a2820000 26940001 1674fffb 2402000c 93b20010
32520040 24030004 0072100a 10000021 00409021 00002821 0411FF63 00000000
2c420002 24030002 24120001 0062900b 240300e9 24130041 0062980b 10000005
24102710 0411FF39 00000000 52000011 00009021 02602021 00002821 0411FF52
00000000 5440fff7 2610ffff 52000009 00009021 24040050 24050200 0411FF4A
00000000 10000003 0002900b 10000002 a2320048 a2320048 8e220054 8e230050
ac430000 0411FF35 00000000 3c029d00 8c420000 8c440000 3c050098 34a59680
0411FE3B 00000000 3c03bf80 ac605800 3c04bf80 ac825830 34028120 ac625800
2e420001 8fbf002c 8fb40028 8fb30024 8fb20020 8fb1001c 8fb00018 03e00008
27bd0030
27bdffd0 afbf002c afb50028 afb40024 afb30020 afb2001c afb10018 afb00014
00809021 00c09821 00e0a821 3c029d00 8c42008c 8c540000 92830048 30630008
00051240 24040051 0043280a 0411FF15 00000000 14400029 24100001 34109c40
241100ff 0411FF04 00000000 14510005 2610ffff 1600fffb 00000000 1000001f
24100001 240300fe 1443001c 24100001 00138823 26310202 12600006 02358823
0411FEF5 00000000 2673ffff 1660fffc 00000000 12400009 02558021 0411FEEE
00000000 a2420000 26520001 1650fffb 00000000 10000004 00000000 26b5ffff
56a0ffff 26b5ffff 0411FEE3 00000000 2631ffff 1620fffc 00008021 8e820054
8e830050 ac430000 0411FEDB 00000000 02001021 8fbf002c 8fb50028 8fb40024
8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0030
27bdffd8 afbf0024 afb30020 afb2001c afb10018 afb00014 00808021 3c029d00
8c42008c 10800012 8c510000 10a0004a 00009821 8e220040 10400047 00859021
92040000 26100001 0411FEB2 00000000 8e220040 2442ffff 1212003e ae220040
5440fff8 92040000 1000003b 00009821 50a00014 8e300040 92230048 30630008
00051240 24040058 0043280a 0411FEB7 00000000 14400030 24130001 240400ff
0411FE9C 00000000 240400fe 0411FE99 00000000 24020200 ae220040 10000026
00009821 26100002 12000008 2610ffff 2412ffff 00002021 0411FE8E 00000000
2610ffff 1612fffc 00002021 0411FE94 00000000 3042001f 24030005 1443000e
24130001 10000005 24101388 0411FE78 00000000 10000002 2610ffff 241200ff
0411FE87 00000000 10520003 2e130001 1600fff6 24130001 8e220054 8e230050
ac430000 0411FE7E 00000000 10000003 02601021 00009821 02601021 8fbf0024
8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0028
27bdffd8 afbf0024 afb30020 afb2001c afb10018 afb00014 00809021 00a09821
3c119d00 8e22003c 0040f809 24040060 00408021 8e22008c ac500000 00001821
00001021 24040018 00031880 02031821 ac600000 24420001 1444fffb 00401821
3c029d00 8c42008c 8c510000 24020060 ae22003c 3c029d00 24421a18 3c039d00
24631dc8 0062202b 10800004 00621023 00529021 10000003 ae320044 00529021
ae320044 ae33004c 3c129d00 8e420028 0040f809 02602021 24030001 00431004
ae220050 8e420024 02602021 0040f809 24050006 ae220054 8e420024 02602021
0040f809 24050005 ae220058 8e420010 02602021 24050008 0040f809 00003021
8e220054 8e230050 ac430000 02001021 8fbf0024 8fb30020 8fb2001c 8fb10018
8fb00014 03e00008 27bd0028
27bdffd0 afbf002c afb40028 afb30024 afb20020 afb1001c afb00018 00a09021
00c0a021 8c820000 8c830004 00432025 14800010 00e09821 3c029d00 8c42008c
8c420000 2410ffff 14400098 2411ffff 8ca40000 8cc50000 0411FF9E 00000000
ae620000 ae600004 00008021 1000008f 00008821 24040001 1444000d 24040002
1460000b 2410ffff 3c029d00 8c42008c 8c420000 10400085 2411ffff 0411FE50
00000000 00408021 10000080 00008821 1444000a 24040003 14600008 00008821
3c029d00 8c42008c 8c440000 0411FAD6 00000000 10000075 305000ff 14440014
24040004 14600012 00000000 82420000 26440001 00821021 a0400001 82430001
24020020 14620005 24030020 24840001 80820000 5043fffe 24840001 0411FB54
00000000 305000ff 10000060 00008821 1444000e 24040005 1460000c 27a60010
26440001 92450000 0411FB7B 00000000 8fa30010 a2430000 ae830000 ae800004
305000ff 10000051 00008821 14440012 24040006 14600010 27a60010 26440001
92450000 0411FBD0 00000000 304200ff 50400004 8fa20010 00408021 10000043
00008821 ae820000 ae800004 00008021 1000003e 00008821 14440007 24040007
14600005 00008821 0411FC52 00000000 10000036 305000ff 54440016 24040008
54600014 24040008 3c109d00 8e02008c 8c520000 0411FD32 00000000 8e020010
8e44004c 00002821 0040f809 00003021 8e03008c 8e020044 0040f809 8c640000
8e02008c ac400000 00008021 1000001f 00008821 14440008 24040009 14600006
00008821 8e440000 0411FC42 00000000 10000016 305000ff 14440004 2404000a
1060000f 24100096 2404000a 1444000e 2410ffff 5460000d 2411ffff 3c029d00
8c42008c 8c420000 8c420028 ae420000 ae400004 00008021 10000004 00008821
10000002 00008821 2411ffff 02001021 02201821 8fbf002c 8fb40028 8fb30024
8fb20020 8fb1001c 8fb00018 03e00008 27bd0030
41909a80 808f418e 49454545 8f8e4949 4f929290 55554f99 9b9a9959 9f9e9d9c
554f4941 a7a6a5a5 abaaa9a8 afae21ac b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc
c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc
e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc
END CFUNCTION 'MIPS32 M4K
'
'******************************************************************************

The only Konstant is Change
 
CircuitGizmos

Guru

Joined: 08/09/2011
Location: United States
Posts: 1427
Posted: 09:59am 10 Aug 2015
Copy link to clipboard 
Print this post

I think that this is a GREAT idea!
Micromites and Maximites! - Beginning Maximite
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 10:12am 10 Aug 2015
Copy link to clipboard 
Print this post

@CG

Thanks.

Hopefully you can independently verify the driver with your hardware, it should just work on a 44 pin 'MX170 although I don't one to test with !

Peter
The only Konstant is Change
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9610
Posted: 02:43pm 10 Aug 2015
Copy link to clipboard 
Print this post

Clever boy!

Well done.
I am sure this will be of great use to those who don't want to tackle the MM+.
Amazing you got all those filesystem features into 7K!
Marvelous.
Smoke makes things work. When the smoke gets out, it stops!
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 02:58pm 10 Aug 2015
Copy link to clipboard 
Print this post

Hi G, thanks, it was quite intense coding/testing to say the least !

I'm working on a way to load CFunctions directly into Flash so that the 3:1 wastage should be got rid of. That way, the 7K CFunction driver will be just that, 7K, and not another 15K of duplicated/wasted flash.

Personally, I think that the 28 pin 'MX170 is great VFM from all kinds of angles and it has legs on it still despite the siren attractions of it's younger but beefier younger sibling .

Also, if we can really crack loadable drivers for MMBasic comprehensively, then of course the MM+ will benefit from being able to have its range of devices supported increased by 3rd party contributors.

Take care

Peter
The only Konstant is Change
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 03:55pm 10 Aug 2015
Copy link to clipboard 
Print this post

Peter, you, my friend, are a BAD ASS!!!!!!!! This is great stuff. I can't wait till all this stuff is put together and out of beta so I can blow my arduino loving friends, library loving minds. Keep up the GREAT work!!!! I want to make a commercial like windows vs macs. "Hi, I'm an arduino, and I'm a uMite..."Edited by viscomjim 2015-08-12
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 04:37pm 10 Aug 2015
Copy link to clipboard 
Print this post

@Jim, Thank You The next step is to make loading up Drivers really simple, and cost as little Flash as possible, which I am working on, but that feature will require a new command (eg Autosave CFunction) to be added to MMBasic, so it may take a beta or two before you will be able to take advantage of it.

@Grogster, PS, I reckon that if I built the FAT32 driver directly into the MMBasic Interpreter, that it would only cost about 5K in Flash !

G'Morning down under, and G'Nite up here ! (sorry to have to bring it up, but what a great Ashes' series we can't often say that !)

Peter
The only Konstant is Change
 
jman

Guru

Joined: 12/06/2011
Location: New Zealand
Posts: 711
Posted: 06:36pm 10 Aug 2015
Copy link to clipboard 
Print this post

Peter this really great well done.


Regards
Jman
 
Frank N. Furter
Guru

Joined: 28/05/2012
Location: Germany
Posts: 949
Posted: 07:50pm 10 Aug 2015
Copy link to clipboard 
Print this post

Thats really amazing!

Is there a way to load different bitmaps with this driver to a TFT???
- that would be great!!!

THANKS!

Frank
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 09:54pm 10 Aug 2015
Copy link to clipboard 
Print this post

Hi Peter,

As others are saying - this is really good stuff

  G8JCF said   . . . it should just work on a 44 pin 'MX170 although I don't one to test with !


Let me know what you need to help test
Will gladly put it in the post for you to have by the end of this week . . .

WWEdited by WhiteWizzard 2015-08-12
 
kiiid

Guru

Joined: 11/05/2013
Location: United Kingdom
Posts: 671
Posted: 10:44pm 10 Aug 2015
Copy link to clipboard 
Print this post

Excellent! This brings life to my good old Microkite modules, because they integrate both MX170 and a uSD card slot :)

http://rittle.org

--------------
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10317
Posted: 12:24am 11 Aug 2015
Copy link to clipboard 
Print this post

  Quote  Hi G, thanks, it was quite intense coding/testing to say the least !


I thought you had been quiet recently

Brilliant bit of coding . I assume this is based on the Petit FAT file system?

What speed are you running SPI? Do you up the SPI speed once the card is initialised?

Please could you confirm the relationship between "write" and "flush". Can I write multiple records and then flush just once? In this case I assume the records end up in the same block if they fit? I assume "write" is:
pf_write(buff, btw, &bw); //Initiate write operation or write next data.
and "flush" is:
pf_write(0, 0, &bw); //Finalize the write operation. If read/write pointer is not on the sector boundary, left bytes in the sector will be filled with zero.

One suggestion for simplification for the user, but please ignore if not sensible, why not combine:

' File.Driver.Init Initialise the Driver
' File.Disk.Init Initialise the Disk Sub-System
' File.Disk.Mount Mount the disk into the filesystem

into a single call with a return that specifies which if any bit fails:

0= success
1= fail to initialise driver
2= fail to initialise disk sub-system
4= fail to mount file system
Edited by matherp 2015-08-12
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 04:13am 11 Aug 2015
Copy link to clipboard 
Print this post

@jman

Thank you.

@FF
Yes there is indeed, it involves using File.Read to read the bitmap into RAM, then using the DrawBitmap API call to write the bitmap from RAM to the display. The RAM will have been allocated using the MALLOC API call. I don't think you can do this entirely in MMBasic but you will need to write a small CFunction to make the call into the DrawBitmap API call. The algorithm is

MALLOC(size of bitmap)
File.Read Bitmap into RAM
BitMapdraw RAM to display

If I get some time I'll create an example to demonstrate, but I'm more interested and focused on getting CFunction binaries loaded directly into Flash.

@WW - Phil

Thank you for such a generous offer, if I had a 44 pin MX170 module then I could test all my various bits of code across all the platforms because then I would have a complete set of 28/44/64/100 pin PIC32MX'X70's here. If you're quite sure then I would love to have one of your MX '170 44 pin modules please.

@MatherP

Yes indeed, one can do as many File.Writes as required and the Driver will automatically flush the bytes to the disk every 512 bytes worth but there is a chance that if there was a power failure then bytes might not have made it to the physical disk and hence would be lost.

Because I was demonstrating a logging capability I wanted to make sure that the chance of losing a record was minimised hence why I flush to disk after every write.

What I think I'll do, is add some functionality to the driver enabling the file to be opened for Writing specifying "with automatic flush after every write" - that should tidy up the user code a bit - flushing after every write does slow down the throughput, but is much more certain, and for an embedded system I would have thought certainty was important, hence a worthwhile alteration

Your idea re combining those three calls is sensible especially in the context of an embedded system where users are not inserting/swapping SDCards as they would on a desktop/laptop system.

Re SPI, I start at 250KHz, then once the SDCard has been successfully mounted switch to 10MHz - which reminds me, I must make the change to the CFunction to only go as fast as "CurrentCpuSpeed >> 2" to allow for CPU 5,10 etc.

Thanks everybody for the generous feedback, it really makes it all the more worthwhile to know that people appreciate one's work.

Peter


The only Konstant is Change
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10317
Posted: 04:28am 11 Aug 2015
Copy link to clipboard 
Print this post

  Quote  Yes there is indeed, it involves using File.Read to read the bitmap into RAM, then using the DrawBitmap API call to write the bitmap from RAM to the display. The RAM will have been allocated using the MALLOC API call. I don't think you can do this entirely in MMBasic but you will need to write a small CFunction to make the call into the DrawBitmap API call. The algorithm is

MALLOC(size of bitmap)
File.Read Bitmap into RAM
BitMapdraw RAM to display

If I get some time I'll create an example to demonstrate, but I'm more interested and focused on getting CFunction binaries loaded directly into Flash.


Peter

This only works in black and white (or other pair of colours) because BitMapdraw only uses 1 bit per pixel.

It needs a more complex CFunction that defines the region and then writes the data to the display itself to deal with 16 or 24-bit colour - basically a complete loadable driver. Also, the data needs to be in a predefined binary form that the CFunction understands (RGB565, RGB888 etc.). Writing out a ".BMP" adds another level of complexity

This is something I would like Geoff to change so DefineRegion is separately callable from DrawRectangle and BitMapDraw and/or add a new routine for outputting a full colour bitmap.

Also, the CFunction will have to be able to write part of the image at a time as there isn't enough RAM to buffer the whole imageEdited by matherp 2015-08-12
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2944
Posted: 04:34am 11 Aug 2015
Copy link to clipboard 
Print this post

  G8JCF said  . . . if I had a 44 pin MX170 module then I could test all my various bits of code across all the platforms because then I would have a complete set of 28/44/64/100 pin PIC32MX'X70's here. If you're quite sure then I would love to have one of your MX '170 44 pin modules please.


Consider it done!

I will build one tonight (Tuesday) and ship tomorrow for delivery Thursday/Friday. Are you're ok with soldering in the headers? If so then I will send the parcel as a large letter; but if not then let me know and I will solder them for you.

Always glad to help you (and others) with the brilliant innovations being made with the MicroMite . . .

WW
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 04:35am 11 Aug 2015
Copy link to clipboard 
Print this post

good point PeterM - only mono bitmaps for now then !
The only Konstant is Change
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 05:02am 11 Aug 2015
Copy link to clipboard 
Print this post

Hi Phil

Thank you very much indeed.

I can still solder headers

BTW, I find that the double sided headers are really useful because I can plug stuff into a breadboard and also attach a dupont socket cable to the top side - I've run out for now but have 10 sticks on order from China due hopefully soon - although sometimes that "slow Boat from (to) China" does seem to be very slow indeed.

Once again, very many thanks Phil, you're a star.

Peter
The only Konstant is Change
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10317
Posted: 05:53am 11 Aug 2015
Copy link to clipboard 
Print this post

Peter

I can confirm this works on the 44-pin

Just one thing in your example above and what I see

  Quote  Number of Existing Log Records : 0
Write Updated Number of Records to disk
Flush data to secure it
Create Header entry if it doesn't exist
Write a simulated Temperature entry to the Log file
Write New Log record out :"10-08-2015","19:01:16","20.32"
Flush log record to secure it

Read and display our logging file
Num Records = 5
Header = Log File Started at 10-08-2015 19:01:03
Record 1 = "10-08-2015","19:01:04","20.86"
Record 2 = "10-08-2015","19:01:09","20.58"
Record 3 = "10-08-2015","19:01:11","20.71"
Record 4 = "10-08-2015","19:01:14","20.29"
Record 5 = "10-08-2015","19:01:16","20.32"


Why does the top line say "Number of Existing Log Records : 0 " when there are already lines in the file?
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10317
Posted: 06:42am 11 Aug 2015
Copy link to clipboard 
Print this post

Peter

Another thing....

If you enable an LCDPANEL

"OPTION LCDPANEL ILI9341,L,23,24,25"

then you get the error:

"Error: Pin 20 is reserved on startup"

when running your program, pin 20 is MOSI on the 44-pin, I assume the error would be on pin 3 on a 28-pin.

Geoff gets round this in the normal SPI OPEN command by testing as below:


if(ExtCurrentConfig[SPI_OUT_PIN] != EXT_BOOT_RESERVED) {
ExtCfg(SPI_OUT_PIN, EXT_DIG_OUT, 0); ExtCfg(SPI_OUT_PIN, EXT_COM_RESERVED, 0);
ExtCfg(SPI_INP_PIN, EXT_DIG_IN, 0); ExtCfg(SPI_INP_PIN, EXT_COM_RESERVED, 0);
ExtCfg(SPI_CLK_PIN, EXT_DIG_OUT, 0); ExtCfg(SPI_CLK_PIN, EXT_COM_RESERVED, 0);
SPI_PPS_OPEN;
}
SpiChnOpen(SPI_CHANNEL1, SPIMode, SPISpeed);
SPIOpen = true;


i.e. if the LCDPANEL is enabled then the pins don't need setting up, just open the SPI channel

In order to be compatible with LCD panels and touch you need to execute this code as part of File.Driver.Init and then execute
" SpiChnOpen(SPI_CHANNEL1, SPIMode, SPISpeed);" as part of every Basic callable function.

You also need to execute SpiChnClose(SPI_CHANNEL1);
at the end of every function and the complete close, as below, as part of File.Driver.Close

if(SPIOpen && ExtCurrentConfig[SPI_OUT_PIN] != EXT_BOOT_RESERVED) {// don't close if it is not open or if it is being used by the LCD
SpiChnClose(SPI_CHANNEL1);
SPI_PPS_CLOSE;
ExtCfg(SPI_OUT_PIN, EXT_NOT_CONFIG, 0); ExtCfg(SPI_INP_PIN, EXT_NOT_CONFIG, 0); // reset to not in use
ExtCfg(SPI_CLK_PIN, EXT_NOT_CONFIG, 0);
}
SPIOpen = false; // show that we are not using it


This then meets Geoff's approach for displays and touch which is that all other SPI usage must open the port before use, and close it again after each usage.
Note that it is important in the File.Driver.Close not to de-allocate the pins without the test or this will kill subsequent touch and display functions

Rather than include the SPI open/close in the Cfunction it may be better to include them in the Basic wrapper for each SD function as this is "safe", just change the speed as required in the Cfunction.

I found this problem while working on the display of pictures from SD. I've got a very quick solution for this but need the above problem fixed before I can progress.

Finally, a request: please could you implement reading/writing complete 512 byte sectors into an array such as BUFFER%(64), or BUFFER!(128)

Result%=File.BlockRead(Buffer%())
Result%=File.BlockWrite(Buffer!())

This then allows a Basic program to do all sorts of things that Petit FAT doesn't support.

Thanks

PeterEdited by matherp 2015-08-12
 
G8JCF

Guru

Joined: 15/05/2014
Location: United Kingdom
Posts: 676
Posted: 02:25pm 11 Aug 2015
Copy link to clipboard 
Print this post

  matherp said  Why does the top line say "Number of Existing Log Records : 0 " when there are already lines in the file?


'Cos there is bug in the MMBasic program I released ! You've got sharp eyes, thank you ! The MMBasic line is currently
PRINT "Number of Existing Log Records :";I%
and it should read
PRINT "Number of Existing Log Records :";NumRecords%


V1.61 attached2015-08-12_002449_SDCardDriverExampleV1.61.zip

and also below

Thanks again PeterM, very well spotted

Peter

OPTION EXPLICIT
OPTION DEFAULT NONE
CPU 48

CONST VER!=1.61

'Using Catalex micro SDCard breakout board
'PIC32MX170 28 Pin wiring
'Pin 2 Chip Select can be any digital output pin
'Pin 3 MOSI
'Pin 14 MISO
'Pin 25 SCLK

PRINT "Test Harness for CFunction FAT32 FileSystem driver (c) Peter Carnegie 2015 Ver";Ver!
PRINT "Simulates use of SDCard for Logging data"

'Set Non-Zero to TRACE program
CONST TRACE = 0

'Number of bytes to show in hex dumps
CONST Length%=&H100

'Useful loop variable
DIM I%=0

'Holds the address returned by Driver.Init
DIM AddrOfRam%=0

'We're using pin 2 for Chip Select
CONST CSPin%=2

'Used for holding filename
'Use dd if=/dev/zero of=logfile.csv bs=1M count=10 to make a blank logfile
DIM FileName$="/logfile.csv"

'Used for byte I/O buffer
DIM Buffer$=STRING$(255," ")

'Offset in file of where to start Reading/Writing From/To
DIM Offset%=0

'Captures number of Bytes READ/WRITTEN
DIM ByteCount%=0

'Used to capture the return values from functions
DIM Result%=-1

'Used for calculating Number of Log Records
DIM NumRecords%

'Appended to each line in the file
CONST CRLF$=CHR$(13)+CHR$(10)

'Quote Character for CSV format
CONST Quot$=CHR$(34)

PRINT "CFunction Driver Version=";File.Ver()

PRINT "Initialise the Driver"
'AddrOfRam%=File.Driver.Init(CSPin%)
Result%=File.Driver.Init(CSPin%, AddrOfRam%)
PError "Failed to Initialise DRIVER. Please Power Cycle system",Result%,1

PRINT "Initialise the disk"
Result%=File.Disk.Init()
PError "Failed to Initialise Disk. Please re-insert media and try again",Result%,1

PRINT "Mount the disk"
Result%=File.Mount.Disk()
PError "Failed to Mount Disk. Please re-insert media and try again",Result%,1

PRINT "Open File ";FileName$
Result%=File.Open(FileName$)
PError "Failed to Open file "+FileName$,Result%,1

PRINT "Get Length of file ";FileName$
Result%=File.Length(ByteCount%)
PError "Failed to get length of "+FileName$,Result%,1
PRINT "File ";FileName$;" is ";ByteCount%;" bytes in size"

PRINT "Get Number of logging records already in file"
Buffer$=STRING$(128," ")
Offset%=0
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Read the first 128 bytes
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read file",Result%,0

'Get number of existing log records
IF INSTR(Buffer$,".0")>0 THEN
NumRecords%=VAL(MID$(Buffer$,1,INSTR(Buffer$,".0")-1))
ELSE
NumRecords%=0
ENDIF
PRINT "Number of Existing Log Records :";NumRecords%

'Update the number of records we've written out to disk
'Increment the number of records because we're going to
'append a new one
NumRecords%=NumRecords%+1
Buffer$=STR$(NumRecords%)+ ".0" +CRLF$

'Now write it back out to disk
Offset%=0
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

PRINT "Write Updated Number of Records to disk"
ByteCount%=0
Result%=File.Write(Buffer$,ByteCount%)
PError "Failed to write to file",Result%,0

PRINT "Flush data to secure it"
Result%=File.Flush()
PError "Flush to disk failed",Result%,0

PRINT "Create Header entry if it doesn't exist"
Offset%=512
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Read the Header block
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read file",Result%,0

'Header exists ?
IF INSTR(1,Buffer$,"Log File")<1 THEN

PRINT "Creating File Header"

Offset%=512
PRINT "Seek to ";Offset%

Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

Buffer$="Log File Started at "+DATE$+" "+TIME$+CRLF$
Result%=File.Write(Buffer$,ByteCount%)
PError "Failed to write to file",Result%,0

Result%=File.Flush()
PError "Flush to disk failed",Result%,0

ENDIF

PRINT "Write a simulated Temperature entry to the Log file"
Offset%=1024+(NumRecords% * 512)
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Simulate temperature logging
Buffer$=Quot$+DATE$+Quot$+","+Quot$+TIME$+Quot$+","+Quot$+STR$(20 + RND(1),2,2)+Quot$+CRLF$
PRINT "Write New Log record out :";Buffer$;
Result%=File.Write(Buffer$,ByteCount%)
PError "Failed to write to file",Result%,0

PRINT "Flush log record to secure it"
Result%=File.Flush()
PError "Failed to Flush data to disk. Error Code:",Result%,0

PRINT
PRINT "Read and display our logging file"
Buffer$=STRING$(128," ")
Offset%=0
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Get Number of Log records
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read File ",Result%,0

'Allow for 10 million records
NumRecords%=VAL(MID$(Buffer$,1,INSTR(Buffer$,".0")-1))
PRINT "Num Records = ";STR$(NumRecords%)

'Get Header
Offset%=512
Result%=File.Seek(Offset%)

Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read File ",Result%,0
PRINT "Header = ";Buffer$;

'Seek to start of logging records
Offset%=1024
Result%=File.Seek(Offset%)
PError "Failed to seek to position "+STR$(Offset%),Result%,0

'Display each Log Record
FOR I%=1 TO NumRecords%
Offset%=1024 + I%*512
Result%=File.Seek(Offset%)
Buffer$=STRING$(128," ")
Result%=File.Read(Buffer$,ByteCount%)
PError "Failed to Read File ",Result%,0
PRINT "Record";STR$(I%,7);" = ";Buffer$;
NEXT I%

PRINT
PRINT "Close File"
Result%=File.Close()
PError "Failed to Close File",Result%,0

PRINT "Close Driver"
Result%=File.Driver.Close()
PError "Failed to Close Driver",Result%,0
IF Result%<>0 THEN
PRINT "Please issue CPU Restart command at MMBasic command prompt"
ENDIF

END

'*************************************************
'
' Debugging Tools
'
'*************************************************

'*************************************************
'
' Print Error Message if Code% is NON-Zero
' END if Hard% is NON-Zero
'
'
SUB PError(Msg$,Code%,Hard%)
IF Code%=0 THEN EXIT SUB
PRINT "Error : ";Msg$;". Error Code:";Code% AND &Hff
IF Hard%<>0 THEN END
END SUB

'*************************************************
'
' Display Hexdump and Result code if TRACE is O
'
'
SUB DoTrace(Msg$, Result%, Numbytes%)
IF TRACE=0 THEN EXIT SUB
PRINT Msg$;" returned &H";HEX$(Result%);
IF NumBytes%<>0 THEN
PRINT " NumBytes:";NumBytes%;
ENDIF
PRINT
HexDump(AddrOfRam%,Length%)
PRINT
PAUSE 10
END SUB


'***********************************************
'
'Do Hex Dump of memory area
'
'
SUB HexDump(Addr%,NumBytes%)

LOCAL I%,J%,L$

PRINT "Address ";
FOR I%=1 TO 16
PRINT " ";HEX$(I%-1);" ";
IF (I%) MOD 4=0 THEN PRINT " ";
NEXT I%

PRINT " ";
FOR I%=0 TO 15
PRINT HEX$(I%);
NEXT I%
PRINT

FOR I%=Addr% TO Addr%+NumBytes%-1 STEP 16
L$=""
FOR J%=0 TO 15
L$=L$ + CHR$(PEEK(BYTE I%+J%))
NEXT J%

PRINT HEX$(I%,8);" ";

FOR J%=1 TO 16
PRINT HEX$(ASC(MID$(L$,J%,1)),2);" ";
IF J% MOD 4 = 0 THEN PRINT " ";
NEXT J%

PRINT " ";

FOR J%=1 TO 16
IF (( ASC(MID$(L$,J%,1)) > &H1F) AND (ASC(MID$(L$,J%,1)) <&H80)) THEN
PRINT MID$(L$,J%,1);"";
ELSE
PRINT ".";
ENDIF
NEXT J%

PRINT

NEXT I%

END SUB


'***********************************************
'
' CUNCTION FAT Filesystem Driver
'
' (c) Copyright Peter Carnegie 2015
'
' File.Driver.Init Initialise the Driver
' File.Driver.Close Close the Driver and release all resources
' File.Disk.Init Initialise the Disk Sub-System
' File.Disk.Mount Mount the disk into the filesystem
' File.Open Open File
' File.Close Close File
' File.Read Read from File
' File.Write Write to File
' File.Flush Flush bytes to disk
' File.Seek Move READ/WRITE pointer to position
' File.Ver Return Driver Version
' File.Length Returns length of File in Bytes
'
' The CFunction can of course be called directly from user code
' These MMBasic wrapper functions just make things neater and tidier !
'
'
'***********************************************


'***********************************************
'
' Initialise the FAT FileSystem Device Driver
'
' CSPinNum% is the pin number used for CS (Chip Select)
'
' Returns the address of the persistent driver memory
'
'
FUNCTION File.Driver.Init(CSPinNum%,Addr%) AS INTEGER

'Get address of the CFunction Driver itself
LOCAL AddrOfSDCard%=PEEK(CFUNADDR Driver.SDCard)

LOCAL Result%=Driver.SDCard(0,AddrOfSDCard%,CSPinNum%,Addr%)

File.Driver.Init=Result%

IF TRACE<>0 THEN
PRINT "Persistent RAM starts at &H";HEX$(Addr%)
ENDIF

DoTrace("Initialise Driver")

END FUNCTION


'***********************************************
'
' Initialise the Disk
'
' Returns 0 if Successful
'
'
FUNCTION File.Disk.Init() AS INTEGER

LOCAL Result%=Driver.SDCard(1)
File.Disk.Init=Result%

DoTrace("Initialise Disk")

END FUNCTION


'***********************************************
'
' Mount the disk
'
' Returns 0 if succesful else non-zero
'
'
FUNCTION File.Mount.Disk() AS INTEGER

LOCAL Result%=Driver.SDCard(2)
File.Mount.Disk=Result%

DoTrace("Mount Disk",Result%)

END FUNCTION


'***********************************************
'
' Open File
'
' Returns 0 if succesful else non-zero
'
'
FUNCTION File.Open(Path$) AS INTEGER

LOCAL Result%=Driver.SDCard(3,Path$)
File.Open=Result%

DoTrace("Open File",Result%)

END FUNCTION


'***********************************************
'
' Read File - Sequential
'
' Returns 0 if succesful else non-zero
' On Entry
'
' On Exit
' Buffer$ will contain the bytes read in from disk
' NumBytes% will contain the number of bytes actually read
' If NumBytes%=0 then End Of File has been reached
'
' Use File.Seek to position the write pointer
'
FUNCTION File.Read(Buffer$, NumBytes%) AS INTEGER

LOCAL Result%=Driver.SDCard(4,Buffer$,NumBytes%)
File.Read=Result%

DoTrace("Read File",Result%)

END FUNCTION


'***********************************************
'
' Write File - Sequential
'
' Returns 0 if succesful else non-zero
' On Entry
' Buffer$ contains the bytes to be written
'
' On Exit
' NumBytes% will contain the number of bytes actually written
'
' Use File.Seek to position the write pointer
'
FUNCTION File.Write(Buffer$,NumBytes%) AS INTEGER

NumBytes%=-1

LOCAL Result%=Driver.SDCard(5,Buffer$,NumBytes%)
File.Write=Result%

DoTrace("Write File",Result%,NumBytes%)

END FUNCTION


'***********************************************
'
' Flush Data to disk
'
' Returns 0 if succesful else non-zero
'
'
FUNCTION File.Flush() AS INTEGER

LOCAL Buffer$=""
LOCAL Offset%=0
LOCAL BytesWritten%=-1

LOCAL Result%=Driver.SDCard(5,Buffer$,BytesWritten%)
File.Flush=Result%

DoTrace("Write File (Flush)",Result%,BytesWritten%)

END FUNCTION


'***********************************************
'
' Close File
'
' Returns 0 if succesful else non-zero
' Flushes any unwritten bytes to the physical disk
'
'
FUNCTION File.Close() AS INTEGER

LOCAL Result%=Driver.SDCard(6)
File.Close=Result%

DoTrace("Close File",Result%)

END FUNCTION


'***********************************************
'
' Drive Close
'
' Returns 0 if succesful else non-zero
' Unconfigures SPI
' Unconfigures CS pin
' FREEs up persistent RAM
'
'
FUNCTION File.Driver.Close() AS INTEGER

LOCAL Result%=0
Result%=Driver.SDCard(7)
File.Driver.Close=Result%

DoTrace("Close Driver",Result%)

END FUNCTION


'***********************************************
'
' File Seek
'
' Returns 0 if succesful else non-zero
' Moves Reading/Writing offset to Position%
'
'
FUNCTION File.Seek(Position%) AS INTEGER

LOCAL Result%=Driver.SDCard(8,Position%)
File.Seek=Result%

DoTrace("File Seek ",Result%)

END FUNCTION


'***********************************************
'
' Driver Version
'
' Returns Driver Version as a FLOAT, eg 1.5
'
'
FUNCTION File.Ver() AS FLOAT

LOCAL Result%=Driver.SDCard(9)
File.Ver=Result% / 100

END FUNCTION


'***********************************************
'
' Length of File
'
' Returns Length of File in Length%
' Returns 0 if OK, non-zero otherwise
'
'
FUNCTION File.Length(Length%) AS INTEGER

LOCAL Result%=Driver.SDCard(10,Length%)
File.Length=Result%

DoTrace("File Length ",Result%)

END FUNCTION


'******************************************************************************
'Created : 2015-08-10 15:20:23 UTC
'Author : Peter Carnegie
'Generator : CFuncGen Ver 2.1.5.0
'
CFUNCTION Driver.SDCard
00000686
10c00006 00801021 00862021 a0450000 24420001 5444fffe a0450000 03e00008
00000000
2407ffff 24c6ffff 10c70008 00001021 80830000 80a20000 00621023 14400003
24840001 1000fff7 24a50001 03e00008 00000000
27bdffe0 afbf001c 3c029d00 8c42008c 8c420000 2c830002 1460001e 8c42005c
8c430014 0083182b 1060001c 24030003 8c450000 14a3001e 000429c2 8c420018
3086007f 27a40010 00a22821 00063080 24070004 04110563 00000000 14400010
24030001 93a30013 00031e00 93a20012 00021400 00621825 93a20010 00621825
93a20011 00021200 00621825 10000004 7c63d800 10000002 24030001 24030001
00601021 8fbf001c 03e00008 27bd0020 1000ffff 00000000
3c029d00 8c42008c 8c420000 8c43005c 2484fffe 8c650014 24a5fffe 0085282b
10a00005 00001021 8c650008 8c620020 70851802 00621021 03e00008 00000000
90830015 00031a00 90820014 00621825 00031c00 9082001b 00021200 9084001a
00441025 03e00008 00621025
27bdffe8 afbf0014 afb00010 00808021 3c029d00 8c42008c 8c420000 8c43005c
ac800000 8c840008 24050001 1085000c 24020001 8c650014 0085282b 10a00009
8fbf0014 50800001 8c64001c ae04000c 0411FFD0 00000000 ae020010 00001021
8fbf0014 8fb00010 03e00008 27bd0018
27bdffe0 afbf001c afb20018 afb10014 afb00010 00808021 3c029d00 8c42008c
8c420000 8c52005c 8c910000 26310001 3231ffff 12200027 24020003 8c830010
50600025 8fbf001c 3222000f 54400020 ae110000 24630001 ac830010 8c84000c
14800007 00111902 8e430010 0223182b 14600016 24020003 10000017 8fbf001c
8e420008 2442ffff 00621024 54400010 ae110000 0411FF75 00000000 00402021
2c430002 1460000b 24020001 8e430014 0083182b 10600007 24020003 ae04000c
0411FF98 00000000 ae020010 ae110000 00001021 8fbf001c 8fb20018 8fb10014
8fb00010 03e00008 27bd0020
27bdffe0 afbf001c afb20018 afb10014 afb00010 00808821 00a09021 0411FFA1
00000000 14400020 00408021 8e260000 30c6000f 02402021 8e250010 00063140
24070020 041104C7 00000000 0002802b 16000016 02001021 92420000 50400012
24100003 9242000b 30420008 14400008 02202021 02402021 8e250004 2406000b
0411FF32 00000000 10400007 02202021 0411FFA0 00000000 1040ffe4 00408021
10000002 02001021 02001021 8fbf001c 8fb20018 8fb10014 8fb00010 03e00008
27bd0020
27bdffe0 afbf001c afb20018 afb10014 afb00010 00a08021 3c029d00 8c42008c
8c520000 8c910004 02202021 24050020 2406000b 0411FF0B 00000000 8e090000
00002021 00001821 24080008 240a002f 2407002e 240b0008 01231021 80450000
30a200ff 24630001 2c460021 14c0001e 306300ff 504a001d 01231821 10470003
0088302b 14c00008 00000000 550b0017 01231821 54470015 01231821 01602021
1000ffed 2408000b 04a10005 2445ff9f 8e450044 00a21021 9042ff80 2445ff9f
30a500ff 2ca5001a 10a00003 02242821 2442ffe0 304200ff a0a20000 24840001
1000ffdd 308400ff 01231821 ae030000 2c420021 a222000b 00001021 8fbf001c
8fb20018 8fb10014 8fb00010 03e00008 27bd0020
27bdffe0 afbf001c afb10018 afb00014 00808021 afa60028 80c20000 24030020
14430006 00a08821 24c60001 afa60028 80c20000 5043fffd 24c60001 2403002f
54430004 ae000008 24c60001 afa60028 ae000008 8fa20028 90420000 2c420020
10400006 02002021 0411FF18 00000000 10000019 a2200000 02002021 27a50028
0411FF9A 00000000 14400013 02002021 02202821 0411FF64 00000000 1440000f
8fbf001c 8e030004 9063000b 5460000c 8fb10018 9222000b 30420010 10400005
02202021 0411FEF6 00000000 1000ffea ae020008 24020003 8fbf001c 8fb10018
8fb00014 03e00008 27bd0020
27bdffe0 afbf001c afb10018 afb00014 00808021 00a08821 240601fe 24070002
0411041F 00000000 14400018 24030003 92040001 00042200 92020000 00822025
7c042620 2402aa55 14820010 24030002 02002021 02202821 24060052 24070002
0411040F 00000000 14400008 24030001 92030001 00031a00 92020000 00621825
7c031e20 38634146 0003182b 00601021 8fbf001c 8fb10018 8fb00014 03e00008
27bd0020
27bdffb8 afbf0044 afb20040 afb1003c afb00038 00808821 3c029d00 8c42008c
8c500000 ae00005c 04110363 00000000 30420001 1440006a 24030002 27a40010
00002821 0411FFC5 00000000 24030001 1443001a 00009021 27a40010 00002821
240601be 24070010 041103E4 00000000 1440005b 24030001 93a20014 10400058
24030006 93b2001b 00129600 93a2001a 00021400 02429025 93a20018 02429025
93a20019 00021200 02429025 27a40010 02402821 0411FFA9 00000000 24040003
10440047 24030001 14400045 24030006 27a40010 02402821 2406000d 24070024
041103C6 00000000 1440003d 24030001 93a2001a 00021200 93a30019 00431025
1440000c 93a30013 93a3002a 00031e00 93a20029 00021400 00621025 93a30027
00431025 93a30028 00031a00 00431025 93a30013 70431002 93a60012 00063200
93a30011 00c33025 02469021 ae320018 93a50010 ae250008 93a30015 00031a00
93a40014 00641825 ae230010 93a40017 00042200 93a70016 00872025 1480000b
00031902 93a70026 00073e00 93a40025 00042400 00e42025 93a70023 00872025
93a70024 00073a00 00872025 00862023 00822023 00832023 0085001b 00a001f4
00002812 24a50002 ae250014 3404fff7 00a4282b 10a00009 24040003 24030006
00601021 8fbf0044 8fb20040 8fb1003c 8fb00038 03e00008 27bd0048 ae240000
93a50032 00052e00 93a40031 00042400 00a42025 93a5002f 00852025 93a50030
00052a00 00852025 ae24001c 02439021 02421021 ae220020 ae200004 ae11005c
1000ffe7 00001821
27bdffa0 afbf005c afb10058 afb00054 00803021 3c029d00 8c42008c 8c420000
8c51005c ae200004 27a20024 afa20014 27a40010 27a50030 0411FEFB 00000000
1440001b 00408021 93a20030 10400017 93a2003b 30420010 54400015 24100003
27a40030 0411FE18 00000000 ae22002c 93a3004f 00031e00 93a2004e 00021400
00621025 93a3004c 00431025 93a3004d 00031a00 00431025 ae220028 ae200024
24020001 10000002 ae220004 24100003 02001021 8fbf005c 8fb10058 8fb00054
03e00008 27bd0060
27bdffd0 afbf002c afb60028 afb50024 afb40020 afb3001c afb20018 afb10014
afb00010 0080a821 00c09821 3c029d00 8c42008c 8c420000 8c50005c acc00000
12000049 24020005 8e030004 30630001 10600045 24020004 8e120028 8e020024
02429023 0245102b 00a2900a 1240003e 00001021 0080a021 24160200 8e020024
304301ff 5460001e 8e060024 8e110008 2631ffff 00021a42 02238824 323100ff
5620000e 8e040030 54400003 8e040030 10000003 8e02002c 0411FD93 00000000
2c430002 50600004 ae020030 ae000004 10000025 24020001 8e040030 0411FDB8
00000000 14400004 00518821 ae000004 1000001d 24020001 ae110034 8e060024
30c601ff 02c61023 0052882b 0251100a 00408821 00002021 0295200b 8e050034
00403821 041102F1 00000000 50400004 8e020024 ae000004 1000000b 24020001
00511021 ae020024 02519023 8e620000 00511021 12400003 ae620000 1000ffc7
0291a021 00001021 8fbf002c 8fb60028 8fb50024 8fb40020 8fb3001c 8fb20018
8fb10014 8fb00010 03e00008 27bd0030
27bdffd0 afbf002c afb60028 afb50024 afb40020 afb3001c afb20018 afb10014
afb00010 00a09021 00c09821 0080a021 3c029d00 8c42008c 8c420000 8c50005c
acc00000 12000077 24020005 8e030004 30640001 10800073 24020004 14a00011
30630040 5060000a 8e030004 00002021 00002821 04110307 00000000 50400004
8e030004 ae000004 10000066 24020001 2402ffbf 00621024 ae020004 10000061
00001021 54600006 8e030028 8e030024 2402fe00 00621024 ae020024 8e030028
8e020024 00621023 0052182b 10600004 24150200 10400053 00409021 24150200
2416ffbf 8e020024 304301ff 54600028 8e110024 8e110008 2631ffff 00021a42
02238824 323100ff 5620000e 8e040030 54400003 8e040030 10000003 8e02002c
0411FD15 00000000 2c430002 50600004 ae020030 ae000004 1000003a 24020001
8e040030 0411FD3A 00000000 14400004 00512821 ae000004 10000032 24020001
ae050034 00002021 041102CA 00000000 50400004 8e020004 ae000004 10000029
24020001 34420040 ae020004 8e110024 323101ff 02b18823 0232102b 0242880a
02802021 02202821 041102BA 00000000 50400004 8e020024 ae000004 10000019
24020001 00511021 ae020024 8e620000 00511021 ae620000 8e020024 304201ff
5440000d 02519023 00002021 00002821 041102A8 00000000 50400004 8e020004
ae000004 10000007 24020001 00561024 ae020004 02519023 1640ffb2 0291a021
00001021 8fbf002c 8fb60028 8fb50024 8fb40020 8fb3001c 8fb20018 8fb10014
8fb00010 03e00008 27bd0030
27bdffe0 afbf001c afb00018 3c029d00 8c42008c 8c500000 00002021 00002821
27a60010 0411FF63 00000000 ae00005c 8fbf001c 8fb00018 03e00008 27bd0020
27bdffd8 afbf0024 afb30020 afb2001c afb10018 afb00014 3c029d00 8c42008c
8c420000 8c50005c 1200004d 24020005 8e030004 30630001 10600049 24020004
8e020028 0044902b 0092100a 00409021 8e030024 ae000024 12400041 00001021
8e110008 10600012 00118a40 2463ffff 2642ffff 0051001b 022001f4 00001012
0071001b 022001f4 00002012 0044102b 54400008 8e04002c 00111023 00431824
ae030024 02439023 10000003 8e040030 8e04002c ae040030 0232102b 10400017
00119823 02519023 0411FC88 00000000 00402021 2c420002 54400006 ae000004
8e020014 0082102b 54400004 ae040030 ae000004 1000001a 24020001 8e020024
00511021 ae020024 02531021 00511821 0223182b 5460ffec 00409021 8e020024
00529021 ae120024 0411FC9E 00000000 54400004 8e040008 ae000004 10000008
24020001 2484ffff 8e030024 00031a42 00831824 00431021 ae020034 00001021
8fbf0024 8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0028
00052840 0085001b 00a001f4 00001012 03e00008 2442ffff
27bdffe0 afbf001c afb10018 afb00014 3c029d00 8c43008c 8c710000 8c420010
3c03bf81 8c65f220 7ca5d800 3c030661 24630053 10a3000b 24040003 3c03bf81
8c64f220 7c84d800 3c030660 24630053 00832026 24030003 24050014 00a4180b
00602021 24050008 0040f809 00003021 3c029d00 8c420010 3c03bf81 8c65f220
7ca5d800 3c030661 24630053 10a3000b 2404000e 3c03bf81 8c64f220 7c84d800
3c030660 24630053 00832026 2403000e 24050029 00a4180b 00602021 24050002
0040f809 00003021 3c029d00 8c420010 3c03bf81 8c65f220 7ca5d800 3c030661
24630053 10a3000b 24040019 3c03bf81 8c64f220 7c84d800 3c030660 24630053
00832026 24030019 2405000e 00a4180b 00602021 24050008 0040f809 00003021
3c02bf81 ac40f230 3c05aa99 24a56655 ac45f230 3c045566 348499aa ac44f230
3c03bf81 8c66f200 7c066b44 ac66f200 3c06bf81 8cc7fa84 24100001 7e071804
acc7fa84 3c06bf81 8cc7fb04 24080003 7d071804 acc7fb04 ac40f230 ac45f230
ac44f230 8c62f200 7e026b44 ac62f200 34038120 3c02bf80 ac435800 3c029d00
8c420000 8c440000 3c050003 34a5d090 0411FF8D 00000000 3c03bf80 ac625830
ae300038 8fbf001c 8fb10018 8fb00014 03e00008 27bd0020
27bdffe8 afbf0014 afb00010 3c029d00 8c43008c 8c700000 8c420010 3c03bf81
8c65f220 7ca5d800 3c030661 24630053 10a3000b 24040003 3c03bf81 8c64f220
7c84d800 3c030660 24630053 00832026 24030003 24050014 00a4180b 00602021
00002821 0040f809 00003021 3c029d00 8c420010 3c03bf81 8c65f220 7ca5d800
3c030661 24630053 10a3000b 2404000e 3c03bf81 8c64f220 7c84d800 3c030660
24630053 00832026 2403000e 24050029 00a4180b 00602021 00002821 0040f809
00003021 3c029d00 8c420010 3c03bf81 8c65f220 7ca5d800 3c030661 24630053
10a3000b 24040019 3c03bf81 8c64f220 7c84d800 3c030660 24630053 00832026
24030019 2405000e 00a4180b 00602021 00002821 0040f809 00003021 3c02bf81
ac40f230 3c05aa99 24a56655 ac45f230 3c045566 348499aa ac44f230 3c03bf81
8c66f200 7c066b44 ac66f200 3c06bf81 8cc7fb04 7c071804 acc7fb04 ac40f230
ac45f230 ac44f230 8c62f200 24040001 7c826b44 ac62f200 ae000038 8fbf0014
8fb00010 03e00008 27bd0018
27bdffe8 afbf0014 3c029d00 8c420004 0040f809 24040064 8fbf0014 03e00008
27bd0018
308400ff 3c02bf80 ac445820 3c03bf80 8c625810 30420001 1040fffd 3c02bf80
8c425820 03e00008 00000000
240300ff 3c02bf80 ac435820 3c03bf80 8c625810 30420001 1040fffd 3c02bf80
8c425820 03e00008 304200ff
27bdffe0 afbf001c afb20018 afb10014 afb00010 309100ff 3c029d00 8c42008c
8c500000 7c111420 04410009 00a09021 24040077 00002821 0411FFF1 00000000
2c430002 1060002f 8fbf001c 3231007f 8e020054 8e030050 ac430000 0411FFDD
00000000 8e020058 8e030050 ac430000 0411FFD8 00000000 02202021 0411FFCA
00000000 00122602 0411FFC7 00000000 7e443c00 0411FFC4 00000000 7e443a00
0411FFC1 00000000 324400ff 0411FFBE 00000000 24020040 12220006 24040095
3a310048 24020001 24030087 00402021 0071200a 0411FFB4 00000000 2410000a
0411FFBC 00000000 7c021c20 04610004 2610ffff 321000ff 1600fff9 00000000
8fbf001c 8fb20018 8fb10014 8fb00010 03e00008 27bd0020
27bdffd0 afbf002c afb40028 afb30024 afb20020 afb1001c afb00018 3c029d00
8c42008c 8c510000 0411FEB7 00000000 8e220054 8e230050 ac430000 2410000a
0411FF9E 00000000 2610ffff 321000ff 1600fffb 24040040 00002821 0411FFA2
00000000 24030001 1443005a 00009021 24040048 240501aa 0411FF9B 00000000
24030001 14430033 240400e9 27b40010 27b30014 02808021 0411FF88 00000000
a2020000 26100001 1613fffb 93a30012 24020001 14620047 00009021 93a30013
240200aa 54620044 a2320048 10000007 24102710 0411FF65 00000000 16000004
240400e9 10000039 00009021 240400e9 3c054000 0411FF7C 00000000 5440fff5
2610ffff 12000033 00009021 2404007a 00002821 0411FF74 00000000 5440002e
a2320048 0411FF65 00000000 a2820000 26940001 1674fffb 2402000c 93b20010
32520040 24030004 0072100a 10000021 00409021 00002821 0411FF63 00000000
2c420002 24030002 24120001 0062900b 240300e9 24130041 0062980b 10000005
24102710 0411FF39 00000000 52000011 00009021 02602021 00002821 0411FF52
00000000 5440fff7 2610ffff 52000009 00009021 24040050 24050200 0411FF4A
00000000 10000003 0002900b 10000002 a2320048 a2320048 8e220054 8e230050
ac430000 0411FF35 00000000 3c029d00 8c420000 8c440000 3c050098 34a59680
0411FE3B 00000000 3c03bf80 ac605800 3c04bf80 ac825830 34028120 ac625800
2e420001 8fbf002c 8fb40028 8fb30024 8fb20020 8fb1001c 8fb00018 03e00008
27bd0030
27bdffd0 afbf002c afb50028 afb40024 afb30020 afb2001c afb10018 afb00014
00809021 00c09821 00e0a821 3c029d00 8c42008c 8c540000 92830048 30630008
00051240 24040051 0043280a 0411FF15 00000000 14400029 24100001 34109c40
241100ff 0411FF04 00000000 14510005 2610ffff 1600fffb 00000000 1000001f
24100001 240300fe 1443001c 24100001 00138823 26310202 12600006 02358823
0411FEF5 00000000 2673ffff 1660fffc 00000000 12400009 02558021 0411FEEE
00000000 a2420000 26520001 1650fffb 00000000 10000004 00000000 26b5ffff
56a0ffff 26b5ffff 0411FEE3 00000000 2631ffff 1620fffc 00008021 8e820054
8e830050 ac430000 0411FEDB 00000000 02001021 8fbf002c 8fb50028 8fb40024
8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0030
27bdffd8 afbf0024 afb30020 afb2001c afb10018 afb00014 00808021 3c029d00
8c42008c 10800012 8c510000 10a0004a 00009821 8e220040 10400047 00859021
92040000 26100001 0411FEB2 00000000 8e220040 2442ffff 1212003e ae220040
5440fff8 92040000 1000003b 00009821 50a00014 8e300040 92230048 30630008
00051240 24040058 0043280a 0411FEB7 00000000 14400030 24130001 240400ff
0411FE9C 00000000 240400fe 0411FE99 00000000 24020200 ae220040 10000026
00009821 26100002 12000008 2610ffff 2412ffff 00002021 0411FE8E 00000000
2610ffff 1612fffc 00002021 0411FE94 00000000 3042001f 24030005 1443000e
24130001 10000005 24101388 0411FE78 00000000 10000002 2610ffff 241200ff
0411FE87 00000000 10520003 2e130001 1600fff6 24130001 8e220054 8e230050
ac430000 0411FE7E 00000000 10000003 02601021 00009821 02601021 8fbf0024
8fb30020 8fb2001c 8fb10018 8fb00014 03e00008 27bd0028
27bdffd8 afbf0024 afb30020 afb2001c afb10018 afb00014 00809021 00a09821
3c119d00 8e22003c 0040f809 24040060 00408021 8e22008c ac500000 00001821
00001021 24040018 00031880 02031821 ac600000 24420001 1444fffb 00401821
3c029d00 8c42008c 8c510000 24020060 ae22003c 3c029d00 24421a18 3c039d00
24631dc8 0062202b 10800004 00621023 00529021 10000003 ae320044 00529021
ae320044 ae33004c 3c129d00 8e420028 0040f809 02602021 24030001 00431004
ae220050 8e420024 02602021 0040f809 24050006 ae220054 8e420024 02602021
0040f809 24050005 ae220058 8e420010 02602021 24050008 0040f809 00003021
8e220054 8e230050 ac430000 02001021 8fbf0024 8fb30020 8fb2001c 8fb10018
8fb00014 03e00008 27bd0028
27bdffd0 afbf002c afb40028 afb30024 afb20020 afb1001c afb00018 00a09021
00c0a021 8c820000 8c830004 00432025 14800010 00e09821 3c029d00 8c42008c
8c420000 2410ffff 14400098 2411ffff 8ca40000 8cc50000 0411FF9E 00000000
ae620000 ae600004 00008021 1000008f 00008821 24040001 1444000d 24040002
1460000b 2410ffff 3c029d00 8c42008c 8c420000 10400085 2411ffff 0411FE50
00000000 00408021 10000080 00008821 1444000a 24040003 14600008 00008821
3c029d00 8c42008c 8c440000 0411FAD6 00000000 10000075 305000ff 14440014
24040004 14600012 00000000 82420000 26440001 00821021 a0400001 82430001
24020020 14620005 24030020 24840001 80820000 5043fffe 24840001 0411FB54
00000000 305000ff 10000060 00008821 1444000e 24040005 1460000c 27a60010
26440001 92450000 0411FB7B 00000000 8fa30010 a2430000 ae830000 ae800004
305000ff 10000051 00008821 14440012 24040006 14600010 27a60010 26440001
92450000 0411FBD0 00000000 304200ff 50400004 8fa20010 00408021 10000043
00008821 ae820000 ae800004 00008021 1000003e 00008821 14440007 24040007
14600005 00008821 0411FC52 00000000 10000036 305000ff 54440016 24040008
54600014 24040008 3c109d00 8e02008c 8c520000 0411FD32 00000000 8e020010
8e44004c 00002821 0040f809 00003021 8e03008c 8e020044 0040f809 8c640000
8e02008c ac400000 00008021 1000001f 00008821 14440008 24040009 14600006
00008821 8e440000 0411FC42 00000000 10000016 305000ff 14440004 2404000a
1060000f 24100096 2404000a 1444000e 2410ffff 5460000d 2411ffff 3c029d00
8c42008c 8c420000 8c420028 ae420000 ae400004 00008021 10000004 00008821
10000002 00008821 2411ffff 02001021 02201821 8fbf002c 8fb40028 8fb30024
8fb20020 8fb1001c 8fb00018 03e00008 27bd0030
41909a80 808f418e 49454545 8f8e4949 4f929290 55554f99 9b9a9959 9f9e9d9c
554f4941 a7a6a5a5 abaaa9a8 afae21ac b3b2b1b0 b7b6b5b4 bbbab9b8 bfbebdbc
c3c2c1c0 c7c6c5c4 cbcac9c8 cfcecdcc d3d2d1d0 d7d6d5d4 dbdad9d8 dfdedddc
e3e2e1e0 e7e6e5e4 ebeae9e8 efeeedec f3f2f1f0 f7f6f5f4 fbfaf9f8 fffefdfc
END CFUNCTION 'MIPS32 M4K
'
'******************************************************************************


The only Konstant is Change
 
     Page 1 of 3    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025