char i,*p;
float f; // same goes for int or alike
p=(char *)&f;
for(i=0; i<sizeof(float); i++) {
putcUSART(*p++);
}
Keep in mind that this value, i.e. the sequence of bytes sent, is "Machine Dependant" (i.e. little endian/big endian sensitive) so the other end of the communication must agree on that.
Hi, Microchip released the first version of their Memory Disk Drive File System Library. It's compatible with FAT16. You can find the documentation and the source files on Microchip website, application note AN1045. I tested the source and sample files with my older hardware design (compact flash card, with bit-transaction), with success. This is exactly what I've been looking and waiting for.....
You can choose how many figures you wish, changing the "02u" and "*100" accordingly, and the "buf" size.
ADDED by Ren:
quote:
All of the other limitations aside, I tried this method and noticed that it fails to handle negative numbers. Adding fabs() to the calculation for the decimal part solves that issue, and only added 3 bytes to the program.
/**************************************************************
Start Bit Subroutine
this routine generates a start bit
(Low going data line while clock is high)
**************************************************************/
void I2CSTART(void) {
// SWStartI2C();
m_I2CClkBit=0; // make sure clock is low
m_I2CDataBit=1; // make sure data is high
I2CDataTris=0; // set data and clock lines for output
I2CDelay();
setClockHigh(); // CLK=1
I2CDelay();
m_I2CDataBit=0; // data line goes low during high clock for start bit
I2CDelay();
m_I2CClkBit=0; // start clock train
I2CDelay();
}
/************************************************************
Stop Bit Subroutine
This routine generates a stop bit
(High going data line while clock is high)
************************************************************/
void I2CSTOP(void) {
// SWStopI2C();
m_I2CDataBit=0; // make sure data line is low
m_I2CClkBit=0; // make sure clock is low
I2CDataTris=0; // set data/clock lines as outputs
m_I2CClkBit=1; // set clock high
I2CDelay();
m_I2CDataBit=1; // data goes high while clock high for stop bit
I2CDelay();
m_I2CClkBit=0; // set clock low again
I2CDelay();
I2CDataTris=1; // set data line as input
// m_I2CClkBit=1; // set clock idle
setClockHigh(); // CLK=1
// questa e' un'altra attesa, per i dispos. (tipo PICBELL, PICWDI2C) che il WAIT lo fanno DOPO lo STOP!
// m_I2CClkBit=0;
I2CDelay();
}
/*************************************************************
BITOUT routine takes the bit of data in C and
transmits it to the serial EE device
*************************************************************/
void I2CBITOUT(byte n) {
I2CDataTris=0; // set data,clock as outputs
if(n) // check for state of data bit to xmit
m_I2CDataBit=1; // output a low bit
else
m_I2CDataBit=0; // high? set data line high
Nop(); // dev'esserci un min. ritardo tra il cambio in DATA e la salita di CLK
Nop();
m_I2CClkBit=1; // set clock line high
I2CDelay();
m_I2CClkBit=0; // return clock line low
I2CDelay();
// retlw 0
}
/**************************************************************
BITIN routine reads one bit of data from the
serial EE device and stores it in C
**************************************************************/
byte I2CBITIN(void) {
/*overlay*/ byte i;
I2CDataTris=1; // make sdata an input line
I2CDelay();
m_I2CClkBit=1; // set clock line high
I2CDelay(); // just sit here a sec
i = m_I2CDataBit ? 1 : 0; // read the data bit
m_I2CClkBit=0; // set clock line low
return i;
}
void setClockHigh(void) {
// Gestisce WAIT_STATE dello slave (CLK basso)... che puo' succedere SEMPRE!
m_I2CClkBit=1;
I2CClkTris=1; // CLK e' input
I2CDelay();
do {
ClrWdt();
} while(!m_I2CClkBit);
I2CClkTris=0; // CLK e' output
}
/****************************************************************
Transmit Data Subroutine
This routine takes the byte of data stored in the
'temp' register and transmits it to the serial EE device.
It will then send 1 more clock to the serial EE for the
acknowledge bit. If the ack bit from the part was low
then the transmission was sucessful. If it is high, then
the device did not send a proper ack bit and the ack
fail LED will be turned on.
****************************************************************/
#define I2CTXSlaveAddrW() I2CTXByte(0xA0)
#define I2CTXSlaveAddrR() I2CTXByte(0xA1)
byte I2CTXByte(byte n) {
/*overlay*/ static byte I2CData,I2CCnt;
I2CData=n;
for(I2CCnt=0; I2CCnt<8; I2CCnt++) { // set the #bits to 8
I2CBITOUT(I2CData & 0x80); // send the bit to serial EE
I2CData <<= 1; // rotate I2CData/txbuf left, bit in CARRY
} // 8 bits done?
// no - go again
// read ack bit
I2CDataTris=1;
I2CDelay();
setClockHigh(); // aspetto ACK
// Per WAIT_STATE dello slave (CLK basso)... NON e' chiaro se PRIMA o DOPO ACK... (PicBell lo fa dopo!)
// questo lo controlla SEMPRE!
I2CDelay();
// dopo Delay, qua arrivo con W=0 e Z=1
I2CCnt=m_I2CDataBit; // Z=1 se ACK=OK (basso), altrimenti Z=0 e W!=0
m_I2CClkBit=0;
if(I2CCnt) { // check ack bit
m_MemCardLedBit=1; // spegne! set acknowledge fail LED if the device did not pull data low
return 0; // 0=ERR
}
return 1; // 1=OK
}
/****************************************************************
Receive data routine
This routine reads one byte of data from the part
into the 'I2CData' register.
****************************************************************/
byte I2CRXByte(void) {
static /*overlay*/ byte I2CData,I2CCnt;
// SWReadI2C();
// I2CData=0; // clear input buffer non serve!
for(I2CCnt=0; I2CCnt<8; I2CCnt++) { // set the #bits to 8
I2CData <<= 1; // rotate I2CData 1 bit left
I2CData |= I2CBITIN(); // read a bit
// STATUSbits.C = 1; // la presenza di ASM disabilita l'ottimizzazione, quindi PEGGIORA!
// Rlcf(input); // Rotate the carry into the data byte
} // 8 bits done?
// no, do another
return I2CData;
}
/****************************************************************
Receive data routine
This routine reads one byte of data from the part
into the 'I2CData' register. It then sends a high
ACK bit to indicate that no more data is to be read
****************************************************************/
byte I2CRX1Byte(void) {
static /*overlay*/ byte I2CData,I2CCnt;
// I2CData=0; // clear input buffer non serve!
for(I2CCnt=0; I2CCnt<8; I2CCnt++) { // set the #bits to 8
// STATUSbits.C = 1; // la presenza di ASM disabilita l'ottimizzazione, quindi PEGGIORA!
// Rlcf(input); // Rotate the carry into the data byte
I2CData <<= 1; // rotate I2CData 1 bit left
I2CData |= I2CBITIN(); // read a bit
} // 8 bits done?
// no, do another
// set ack bit = 1
I2CBITOUT(1); // to finish transmission
return I2CData;
}
/**************************************************************
READ (read routine)
This routine reads 8 consecutive addresses of the
serial EE device starting at address 00 in the
random access mode (non-sequential read). Reading
the device using the random access mode
requires that the address pointer be set for every
byte before the read takes place. The address pointer
is set by sending a 'write mode' control byte with the
address of the location to read.
***************************************************************/
byte I2CReadRandom(byte n) {
static /*overlay*/ byte I2CData;
// bcf port_a,ackf ; clear the ack fail LED if on
I2CSTART(); // generate start bit
//
// now send the write control byte and
// address to set the pointer
//
I2CTXSlaveAddrW(); // get slave address and write mode
// movfw I2CAddr ; get word address
I2CTXByte(n); // and send it
// now read one byte from the part
I2CSTART(); // generate start bit
I2CTXSlaveAddrR(); // get slave address and read mode
I2CData=I2CRX1Byte(); // read 1 byte from serial EE
I2CSTOP(); // send stop bit to end transmission
return I2CData;
}
byte I2CReadRandom16(word n) {
byte I2CData;
// bcf port_a,ackf ; clear the ack fail LED if on
I2CSTART(); // generate start bit
//
// now send the write control byte and
// address to set the pointer
//
I2CTXSlaveAddrW(); // get slave address and write mode
// move word address (HIGH)
I2CTXByte(*(((byte *)&n)+1)); // and send it
// move word address (LOW)
I2CTXByte(*((byte *)(&n))); // and send it
// now read one byte from the part
I2CSTART(); // generate start bit
I2CTXSlaveAddrR(); // get slave address and read mode
I2CData=I2CRX1Byte(); // read 1 byte from serial EE
I2CSTOP(); // send stop bit to end transmission
return I2CData;
}
/**************************************************************
READ (sequential read routine)
This routine reads 8 consecutive addresses of the
serial EE device starting at address 00 in the
sequential read mode. Reading in this mode is more
efficient than the random read mode as the control byte
and address have to be sent only once at the beginning
of the sequence. As many consecutive addresses as
needed can then be read from the part until a stop bit is
sent. In the read mode, the PIC 16C54 must send the acknowledge
bit after every 8 data bits from the device. When the
last byte needed has been read, then the controller will
send a high acknowledge bit and then a stop bit to halt
transmission from the device.
***************************************************************/
byte I2CRead8Seq(byte n,byte I2CCntB) { // entra W=indirizzo part. lettura, FSR punta al buffer
static /*overlay*/ byte *p;
// bcf port_a,ackf ; clear the ack fail LED if on
p=I2CBuffer; // bank1, ISP=0!
I2CSTART(); // generate start bit
I2CTXSlaveAddrW(); // send slave address and write mode
// get word address
I2CTXByte(n); // and send it
I2CSTART(); // generate start bit
I2CTXSlaveAddrR(); // send slave address and read mode
I2CRead8Seq2:
*p++=I2CRXByte(); // read 1 byte from device
if(!--I2CCntB) { // are all 8 bytes read?
// no, send low ack and do another
// yes, send high ack bit
I2CBITOUT(1); // to stop tranxmission
I2CSTOP(); // and send a stop bit
return 8;
}
// send low ack bit
I2CBITOUT(0); // to continue transmission
goto I2CRead8Seq2; //and read another byte
}
/**************************************************************
READ16 (sequential read routine)
This routine reads 8 consecutive addresses of the
serial EE device starting at given 16bit address in the
sequential read mode. Reading in this mode is more
efficient than the random read mode as the control byte
and address have to be sent only once at the beginning
of the sequence. As many consecutive addresses as
needed can then be read from the part until a stop bit is
sent. In the read mode, the PIC 16C54 must send the acknowledge
bit after every 8 data bits from the device. When the
last byte needed has been read, then the controller will
send a high acknowledge bit and then a stop bit to halt
transmission from the device.
***************************************************************/
byte I2CRead16Seq(word n,byte I2CCntB) { // entra indirizzo part. lettura, FSR punta al buffer
static /*overlay*/ byte *p;
// bcf port_a,ackf ; clear the ack fail LED if on
I2CSTART(); // generate start bit
I2CTXSlaveAddrW(); // send slave address and write mode
// move word address (HIGH)
I2CTXByte(*(((byte *)&n)+1)); // and send it
// move word address (LOW)
I2CTXByte(*((byte *)(&n))); // and send it
I2CSTART(); // generate start bit
I2CTXSlaveAddrR(); // send slave address and read mode
p=I2CBuffer;
I2CRead16Seq2:
*p++=I2CRXByte(); // read 1 byte from device
if(!--I2CCntB) { // are all n bytes read?
// no, send low ack and do another
// yes, send high ack bit
I2CBITOUT(1); // to stop tranxmission
I2CSTOP(); // and send a stop bit
return 16;
}
// send low ack bit
I2CBITOUT(0); // to continue transmission
goto I2CRead16Seq2; // and read another byte
}
byte I2CReadRTC(byte I2CCntB) { // entra num. byte da leggere, buffer
static /*overlay*/ byte *p;
// bcf port_a,ackf ; clear the ack fail LED if on
p=I2CBuffer; // bank1, ISP=0!
I2CSTART(); // generate start bit
I2CTXByte(0xD0); // DS1337C
// send slave address and read mode
I2CTXByte(0); // send register address
I2CSTART(); // generate start bit
I2CTXByte(0xD1); // DS1337C
I2CRead8Seq2:
*p++=I2CRXByte(); // read 1 byte from device
if(!--I2CCntB) { // are all 8 bytes read?
// no, send low ack and do another
// yes, send high ack bit
I2CBITOUT(1); // to stop tranxmission
I2CSTOP(); // and send a stop bit
return 1;
}
// send low ack bit
I2CBITOUT(0); // to continue transmission
goto I2CRead8Seq2; //and read another byte
}
/****************************************************************
Byte Write Routine
This routine writes the data in "temp" to
8 consecutive bytes in the serial EE device starting
at address 00. This routine waits 10mS after every
byte to give the device time to do the write. This
program repeats forever.
*****************************************************************/
void I2CWriteByte(byte n, byte b) {
static /*overlay*/ byte I2CAddr,I2CCnt;
// SWWriteI2C();
// clrf port_a ; clear all LEDs
I2CAddr=n; // set starting address to W
// temp=0x55; // set data to write as 55h
// set number of bytes
for(I2CCnt=0; I2CCnt<8; I2CCnt++) { // set the #bits to 8
I2CSTART(); // generate start bit
I2CTXSlaveAddrW(); // send slave address and write mode
// move word address
I2CTXByte(I2CAddr); // and send it
I2CTXByte(b); // move data byte and transmit it
I2CSTOP(); // generate stop bit
// movlw 10
// movwf loops ; set delay time to give
// call WAIT ; 10 ms wait after every byte
I2CWritePagePoll();
I2CAddr++; // add 1 to address counter
} // all 8 bytes written?
// no, do another byte
}
/****************************************************************
Page Write Routine
This routine uses page mode to write the data in "temp" to
8 consecutive bytes in the serial EE device starting
at address 00. This routine waits 10mS after every
page to give the device time to do the write. This
routine executes forever
*****************************************************************/
void I2CWritePage(byte n,byte I2CCntB) { // entra W=indirizzo part. lettura, (FSR usato per buffer)
static /*overlay*/ byte *p;
// clrf port_a ; clear all LEDs
p=I2CBuffer;
I2CSTART(); // generate start bit
I2CTXSlaveAddrW(); // send slave address and write mode
// move word address
I2CTXByte(n); // and send it
do {
I2CTXByte(*p++); // and transmit it
} while(--I2CCntB); // all n bytes written?
// no, do another
I2CSTOP(); // yes,generate stop bit
// movlw 10
// movwf loops ; set delay time to give
// call WAIT ; 10 ms wait after every byte
Delay_mS(20); // 50mS
}
void I2CWriteRTC(byte n,byte I2CCntB) { // entra W=indirizzo part. lettura, (FSR usato per buffer)
static /*overlay*/ byte *p;
// clrf port_a ; clear all LEDs
p=I2CBuffer;
I2CSTART(); // generate start bit
// send slave address and write mode
I2CTXByte(0xD0); // DS1337C
// move register address
I2CTXByte(n); // and send it
do {
I2CTXByte(*p++); // and transmit it
} while(--I2CCntB); // all n bytes written?
// no, do another
I2CSTOP(); // yes,generate stop bit
// movlw 10
// movwf loops ; set delay time to give
// call WAIT ; 10 ms wait after every byte
}
/****************************************************************
Page Write 16 Routine (8 bytes, address a 16 bit)
This routine uses page mode to write the data in "temp" to
8 consecutive bytes in the serial EE device starting
at given address . This routine waits 10mS after every
page to give the device time to do the write. This
routine executes forever
*****************************************************************/
#define I2CWritePage16Default() I2CWritePage16((word)&I2CAddr)
byte I2CWritePage16(word n,byte I2CCntB) { // entra W=puntat. all'indirizzo part. lettura, (FSR usato per buffer)
static /*overlay*/ byte *p;
// clrf port_a ; clear all LEDs
I2CSTART(); // generate start bit
I2CTXSlaveAddrW(); // send slave address and write mode
// move word address (HIGH)
I2CTXByte(*(((byte *)&n)+1)); // and send it
// move word address (LOW)
I2CTXByte(*((byte *)(&n))); // and send it
p=I2CBuffer;
do {
I2CTXByte(*p++); // and transmit it
} while(--I2CCntB); // move data byte
// all n bytes written?
// no, do another
I2CSTOP(); // yes,generate stop bit
// movlw 10
// movwf loops ; set delay time to give
// call WAIT ; 10 ms wait after every byte
Delay_mS(20); // 20mS
return 16;
}
byte I2CWritePagePoll(void) {
byte I2Cpollcnt,i;
I2Cpollcnt=100; // set max number of times to poll as 100
do {
I2CSTART(); // generate start bit
i=I2CTXSlaveAddrW(); // send slave address and write mode
if(i) // was the ack bit low?
goto exitpoll; // yes, do another byte
} while(--I2Cpollcnt); // is poll counter down to zero?
// no, poll again. Otherwise the part is
// bsf port_a,timeout ; not responding in time so set timeout LED and continue on
exitpoll:
;
}
void I2CDelay(void) { // circa 2,5uSec (400KHz operation)
/*overlay*/ static byte uSec; // 1.25 ca.
uSec=1;
do {
ClrWdt(); // Clear the WDT
Delay1TCY(); // TARARE!! @48MHz??
Delay1TCY();
Delay1TCY();
// Delay1TCY();
} while(--uSec);
}
(unfortunately this can't be retrieved from cache... will try reposting it.)
< Message edited by DarioG -- Dec. 4, 2007 1:59:10 AM >
/** I N T E R R U P T V E C T O R S *****************************************/
#pragma code high_vector=0x08
#define SILICON_REV_A3
void interrupt_at_high_vector(void) {
_asm
#ifdef SILICON_REV_A3
CALL Foo, 1 // store current value of WREG,BSR, STATUS for a second time
RETFIE 1 // FAST
Foo:
POP // clears return address of Foo call
goto high_isr
#else
goto high_isr
#endif
_endasm
}
#pragma code
#pragma code low_vector=0x18
void interrupt_at_low_vector(void) {
_asm goto low_isr _endasm
}
#pragma code
/** D E C L A R A T I O N S **************************************************/
/******************************************************************************
* Function: void high_isr(void)
* PreCondition: None
* Input:
* Output:
* Side Effects:
* Overview:
*****************************************************************************/
#pragma interrupt high_isr // nosave=section("MATH_DATA"),section(".tmpdata") // OPTIONAL
void high_isr(void) {
if(INTCONbits.TMR0IF) { // Timer 0.. EXAMPLE
INTCONbits.TMR0IF=0; // clear bitIRQ
}
}
/******************************************************************************
* Function: void low_isr(void)
* PreCondition: None
* Input:
* Output:
* Side Effects:
* Overview:
*****************************************************************************/
#pragma interruptlow low_isr //nosave=section("MATH_DATA"),section(".tmpdata") //OPTIONAL
void low_isr(void) {
}
#pragma code
// calcola la parita': entra W, esce 0 se E e 1 se O
BOOL GetParita(byte n) {
static byte p;
#ifdef DARIO
p=n >> 1; // Microchip AN774
p ^= n;
n= p >> 2;
p ^= n;
n= p >> 4;
p ^= n;
return (p & 1);
#endif
#ifdef OLDPARITA
if(n & 0x1)
p++;
if(n & 0x2)
p++;
if(n & 0x4)
p++;
if(n & 0x8)
p++;
if(n & 0x10)
p++;
if(n & 0x20)
p++;
if(n & 0x40)
p++;
if(n & 0x80)
p++;
#endif
//From: John Payson
//comments from Andrew Warren of Fast Forward Engineering
//8-bit parity
//This routine will leave the parity of X in X.0
// while blenderizing most of the rest of X
p=n;
_asm
movlb p
swapf p, 0, 1 //x= abcdefgh w = efghabcd
xorwf p, 1, 1 //x= abcdefgh w = efghabcd
// xor efghabcd
rrncf p, 0, 1 //x= abcdefgh w = -abcdefg
// xor efghabcd xor -efghabc
xorwf p, 1, 1 //x= abcdefgh w = -abcdefg
// xor efghabcd xor -efghabc
// xor -abcdefg
// xor -efghabc
// at this point, the parity for half the bits
// (a, b, e, and f) is in bit 2 of X, and the
// parity for the other half (bits c, d, g, and h)
// is in bit 0 of X.
btfsc p, 2, 1 // if the parity of (a,b,e,f) is 0,
// then the parity of (a,b,c,d,e,f,g,h)
// is equal to the parity of (c,d,g,h)...
// which is already in bit 0, so skip ahead.
incf p, 1, 1 // otherwise, the parity of (a,b,e,f) is 1,
// so the parity of (a,b,c,d,e,f,g,h) is
// NOT equal to the parity of (c,d,g,h).
// invert bit 0.
// at this point, bit 0 contains the parity of
// (a,b,c,d,e,f,g,h).
_endasm
#ifdef RIC
CheckParity:
swapf X, w ; John's idea: reducing byte to nibble
xorwf X, w
addlw 41H ; bit 1 becomes B0^B1 and bit 7 becomes B6^B7
iorlw 7CH ; for carry propagation from bit 1 to bit 7
addlw 2 ; Done! the parity bit is bit 7 of W
andlw 80H ; set NZ if odd parity, and leave 00 or 80 in W
return
#endif
#define PARITY(b) ((((((b)^(((b)<<4)|((b)>>4))) + 0x41) | 0x7C ) +2 ) & 0x80)
return p & 1;
}
guys here is my finished and tested circular buffa code if anyone wants it!!! feel free to copy it.
this one is well suited for USART becuase it works with null terminated strings... and returns a null if empty...
this one handles empty and full also.
unsigned int head, tail = 0; unsigned int length = 127; unsigned char buffer_full=0; unsigned char buffer_empty=1; char rcv_buffa[128];
//write a byte to receive buffa //this process assumes tail is always an empty spot //if tail=head then empty , if (tail= head -1) then full // void write_rcvbuffa(unsigned char blah123) { //check for a full buffer if ((buffer_full) | ((tail+1)==head) | ((tail==length) & (head==0))) { xbee_rts=1; //inhibit unit from sending more data buffer_full=1; } //if buffer not full else { //write the byte and inc to next empty slot rcv_buffa[tail] = blah123; if (tail >= length) { tail = 0; } else { tail++; }
//update flags buffer_empty=0; if (((tail+1)==head) | ((tail==length) & (head==0))) { buffer_full=1; xbee_rts=1; //inhibit more stuff from comming until buffer is not empty } } } //end write a byte to receive buffa
// read a byte from receive buffer unsigned char read_rcvbuffa(void) {
//return a null if buffer is empty, otherwise read 1 from head and increment // then returns the value at head. // then examines if buffer is empty and sets flag as appropriate for next read (or write) if ((buffer_empty) | (head==tail)) { Data1=0x00; //null value xbee_rts=0; //good to go buffer_empty=1; } else { //read 1 from head and inc head Data1 = rcv_buffa[head]; if (head >= length) { head = 0; } else { head++; }
//update flags buffer_full=0; xbee_rts=0; if (head==tail) { buffer_empty=1; xbee_rts=0; //good to go } } return Data1; } // end read byte from receive buffa
lemme know if anyone needs additional info or help with it :)
this one is tested with xbee pro module as a receive buffer.
im gonna use it for a transmit one too i think.
the RTS control stuff can be deleted if your not using it... (or not using an xbee module hahah)
< Message edited by corvette321 -- Dec. 13, 2007 9:44:51 AM >
although there is a brief example of how to use the commands _erase_flash(), _write_flash16() and _write_flash24() that were added in C30 v3.01. This example shows how to write arrays that exceed the page boundary:
// Flash_Write Test_011008.c
//
// A test for demonstrating how to write a large array to FLASH (Program Memory)
// on the dsPIC33FJ256GP710 processor installed in the Explorer16 development
// board. Objective: Define and write an array of 2048 16 bit words to FLASH.
#include "libpic30.h"
#include "p33Fxxxx.h"
// _FLASH_PAGE is a static definition (512 for the dsPIC33).
// _FLASH_ROW is a static definition (64 for the dsPIC33).
// Define an array of 2048 words in program memory.
int FLASH_data[_FLASH_PAGE*4] __attribute__((space(prog),aligned(_FLASH_PAGE*8)));
int main()
{
int data_index;
int page_index;
int row_index;
int Test_data[_FLASH_ROW];
unsigned long Flash_pointer;
// initialize some data for this test
for (data_index = 0; data_index < _FLASH_ROW; )
{
Test_data[data_index] = data_index;
data_index++;
}
// Get the address of the predefined variable(s)in program space.
_init_prog_address(Flash_pointer, FLASH_data);
// This outer loop is used to erase each page after the page boundary has been crossed.
for (page_index = 0; page_index < 4; )
{
_erase_flash(Flash_pointer); // erase a page.
// The row level loop. 8 rows per page for the dsPIC33
for (row_index = 0; row_index < 8; )
{
// Write each row here with 64 words of data.
_write_flash16(Flash_pointer, Test_data);
// increment the values for the test data before writing the next row.
// NOTE: This is a post increment so it will increment once more
// after the final row is written.
for (data_index = 0; data_index < _FLASH_ROW; )
{
Test_data[data_index] += 64;
data_index++;
}
asm("nop"); // nops here for breakpoint placement.
asm("nop");
asm("nop");
asm("nop");
// Increment the Flash_pointer by one row.
Flash_pointer += (_FLASH_ROW * 2);
// NOTE: No additional addressing action is required when
// page boundaries are crossed. However, the page boundary
// must be kept track of since the page erase function is
// used prior to the writing of rows on a page.
// Increment the row index.
row_index++;
}
asm("nop"); // nops here for breakpoint placement.
asm("nop");
asm("nop");
asm("nop");
// Increment the page index.
page_index++;
}
asm("nop"); // Place Breakpoint here, then read the part to show data in FLASH.
asm("nop");
asm("nop");
asm("nop");
}
Issue at hand is a fast way to do float sqrt(float) or invsqrt to a reasonable accuracy...
code:
float fastSqrt(float x) { union { float f; unsigned long ul;} y; y.f = x; y.ul = (0xbe6eb50cul - y.ul ) >> 1; y.f = 0.5f * y.f * (3.0f - x * y.f * y.f ); //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f ); //repeat iterations to achieve lower error //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f ); //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f ); //y.f = 0.5f * y.f * (3.0f - x * y.f * y.f ); //y.f ~= 1.0f/sqrt(x) return y.f * x; // sqrt(x) = x / sqrt(x), return just y.f if you need invsqrt(x) }
runs in about 123us on a pic18 @ 41.66666mhz vs clib sqrt(x) function at about 604us, (mplab sim, 1 newton step).
error functions can be found in the pdf listed about and newton steps can be added or subtracted as needed for accuracy...1 step yields max relative error <= ~.00175
i ran through the math far enough to find that doing a new version for sqrt(x) would not be faster to run than calculating 1.0/sqrt(x) and multiplying by x to get sqrt(x) as the newton step would require divisions.