Author Archive
CRC With dsPIC
by Martyn on Mar.23, 2009, under News
CRC’s are probably the most time consuming thing you can do in a data stream, but they have their uses - and not just for checking that data is correct, but more on that in a later post.
I found that the microchip documentation extremely useful, and I suspect you will to: Section 36 PCRC. But the biggest shout out should go to billysdomain in the Microchip Forums who actually got it working, the bits which make it work are his code, lets begin:
-
-
int CalculateCRC(DataPL *DataPacket)
-
{
-
unsigned int j, length = (DATAPL_LEN*2)-2;
-
unsigned char *ptr, *data;
-
ptr = (unsigned char *)&CRCDAT;
-
-
CRCCON = 0×0F; // Configure the polynomial length (PLEN)
-
_CRCIF = 0; // Clear the CRC flag
-
_CRCIE = 1; // Enable the int
-
-
CRCXOR = 0×1021; // Polynomial - crc-16
-
CRCWDAT = 0×0000; // Initialize CRCWDAT with 0
-
-
data = (*DataPacket).CHARS;
-
-
length >>= 1;
-
for(j = 0; j < length; j++)
-
{
-
//Must use pairs of bytes to get the correct result
-
*ptr = *data++; //write data into FIFO
-
*ptr = *data++; //write data into FIFO
-
-
if (CRCCONbits.CRCFUL) //check if FIFO is full
-
{
-
CRCCONbits.CRCGO = 1; //start CRC engine
-
while (!CRCCONbits.CRCMPT); //check if FIFO is empty
-
CRCCONbits.CRCGO = 0; //stop CRC engine
-
}
-
}
-
-
CRCDAT = 0×0000;
-
CRCCONbits.CRCGO = 1; // (Re)Start the calculation
-
-
comms_datapacket = DataPacket; // Save a reference
-
// With a bit of luck CRC finishes before we send
-
// the data via SPI…
-
-
return 1;
-
}
-
-
//Use the software CRC calculator
-
static const unsigned int CRC16Table[256] = {
-
0×0000,0×1021,0×2042,0×3063,0×4084,0×50a5,0×60c6,0×70e7,
-
0×8108,0×9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
-
0×1231,0×0210,0×3273,0×2252,0×52b5,0×4294,0×72f7,0×62d6,
-
0×9339,0×8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
-
0×2462,0×3443,0×0420,0×1401,0×64e6,0×74c7,0×44a4,0×5485,
-
0xa56a,0xb54b,0×8528,0×9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
-
0×3653,0×2672,0×1611,0×0630,0×76d7,0×66f6,0×5695,0×46b4,
-
0xb75b,0xa77a,0×9719,0×8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
-
0×48c4,0×58e5,0×6886,0×78a7,0×0840,0×1861,0×2802,0×3823,
-
0xc9cc,0xd9ed,0xe98e,0xf9af,0×8948,0×9969,0xa90a,0xb92b,
-
0×5af5,0×4ad4,0×7ab7,0×6a96,0×1a71,0×0a50,0×3a33,0×2a12,
-
0xdbfd,0xcbdc,0xfbbf,0xeb9e,0×9b79,0×8b58,0xbb3b,0xab1a,
-
0×6ca6,0×7c87,0×4ce4,0×5cc5,0×2c22,0×3c03,0×0c60,0×1c41,
-
0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0×8d68,0×9d49,
-
0×7e97,0×6eb6,0×5ed5,0×4ef4,0×3e13,0×2e32,0×1e51,0×0e70,
-
0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0×9f59,0×8f78,
-
0×9188,0×81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
-
0×1080,0×00a1,0×30c2,0×20e3,0×5004,0×4025,0×7046,0×6067,
-
0×83b9,0×9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
-
0×02b1,0×1290,0×22f3,0×32d2,0×4235,0×5214,0×6277,0×7256,
-
0xb5ea,0xa5cb,0×95a8,0×8589,0xf56e,0xe54f,0xd52c,0xc50d,
-
0×34e2,0×24c3,0×14a0,0×0481,0×7466,0×6447,0×5424,0×4405,
-
0xa7db,0xb7fa,0×8799,0×97b8,0xe75f,0xf77e,0xc71d,0xd73c,
-
0×26d3,0×36f2,0×0691,0×16b0,0×6657,0×7676,0×4615,0×5634,
-
0xd94c,0xc96d,0xf90e,0xe92f,0×99c8,0×89e9,0xb98a,0xa9ab,
-
0×5844,0×4865,0×7806,0×6827,0×18c0,0×08e1,0×3882,0×28a3,
-
0xcb7d,0xdb5c,0xeb3f,0xfb1e,0×8bf9,0×9bd8,0xabbb,0xbb9a,
-
0×4a75,0×5a54,0×6a37,0×7a16,0×0af1,0×1ad0,0×2ab3,0×3a92,
-
0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0×9de8,0×8dc9,
-
0×7c26,0×6c07,0×5c64,0×4c45,0×3ca2,0×2c83,0×1ce0,0×0cc1,
-
0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0×8fd9,0×9ff8,
-
0×6e17,0×7e36,0×4e55,0×5e74,0×2e93,0×3eb2,0×0ed1,0×1ef0
-
};
-
-
unsigned int ChecksumCalcS(unsigned char *data, unsigned int len)
-
{
-
unsigned int crc = 0;
-
unsigned int i;
-
for(i = 0; i < len; i++)
-
{
-
crc = (crc << 8) ^ CRC16Table[((crc >> 8) ^ *data++)];
-
}
-
return crc;
-
}
-
-
void __attribute__((__interrupt__)) _NOPSV _CRCInterrupt(void)
-
{
-
unsigned short hardware, software;
-
-
_CRCIF = 0; // Clear the interrupt
-
-
while(!CRCCONbits.CRCMPT); // Wait for CRC shifter to clear FIFO
-
(*comms_datapacket).CRC = CRCWDAT;
-
-
hardware = CRCWDAT;
-
software = ChecksumCalcS((*comms_datapacket).CHARS,
-
(DATAPL_LEN*2)-2);
-
-
CRCWDAT = 0;
-
}
-
Ok, a lot of things to note
- This code will not work on its own
- Putting a breakpoint on the last line of code will allow a software / hardware comparison
- _NOPSV is a macro (google it)
- The DataPL datatype is a union of an int array, char array and a large bitfield which allows me to have loads of small (or large) data types of non-standard size.
- The interrupt is not required if working with more than 8 bytes of data as you need to wait for the buffer to clear before filling it - so might as well wait for it all to happen
- This uses 8-bit data rather than 16-bit data, if you have a working example of this with a software table based alternative please email me! the table means I can calculate the CRC in C#
- Most of code is by billysdomain - I was 80% there, missing 2 lines in my implementation, should have rtfm (more)
Anyhow, hope this helps someone. I might do a quick post on using CRC for synchronising serial streams soon, guess how that’s done :p
Timering with DSPic’s
by Martyn on Mar.22, 2009, under Microcontrollers, Robots
Timers on DSPics are easy - and after helping a few people out with timers at uni I thought I would post a really quick how-to on setting up a timer to interrupt at a set frequency. First lets start with a few bits you need to know:
Fosc = 40000000;
That’s it
Just make sure that this value is the number in Hz on your oscillator (or a multiple of it if using PLL)
Next its important to remember there are different types of timers on a pic, do some research and rtfm before doing any pic / embedded work - will save you hours, I am using timer 1 - as its the first one in the manual :p
Next bits:
-
-
-
T1CONbits.TCKPS = 0×02; // Select the PRESCALER
-
TMR1 = 0×00; // Make sure the timer is starting from zero
-
PR1 = 600; // How long the timer should run before an interrupt (in timer ticks)
-
_T1IF = 0; // Clear the interrupt flag
-
_T1IE = 1; // Enable the interrupt
-
T1CONbits.TON = 1; // Turn the interrupt on
-
-
void __attribute__((__interrupt__)) __attribute__((no_auto_psv)) _T1Interrupt(void)
-
{
-
// Funky interrupt code goes
-
}
-
-
To explain, the prescale waits x many ticks before incrementing the timer counter and is usually a set number like 1,8,32 or 64. To calculate the number for PR1 you then juse a very simple formula:


Where Freq is your desired interrupt frequency. Then just round the value of PR1 to the nearest integer if it is not one already. Simple!
As a side note - more information to why the interrupt function has a no_auto_psv attribute can be found at FlyingPic24.com
Hope this has been useful - please comment if you have any corrections/questions/comments.
Its been a sufficiently long time, so to blogging again
by Martyn on Mar.13, 2009, under Micromouse, News
Heh, aside from lots of lectures and not so much coursework nothing to exciting has happened since the last blog entry. Apart from maybe this:
Do now need a name for it tho - Any ideas the random few who might happen across this page?
Micromouse has shrunk a bit…
by Martyn on Oct.19, 2008, under Microcontrollers, Robots
A bit (lot) late, but I just noticed a video posted on youtube with a 1/2 size micromouse - Its tiny!
Anyhow, I have been working on my mouse as it is also my 4th (and final) year project for my MEng Cybernetics degree. Been working on the motor housing and choosing the components for the hardware, to make sure it all fits I built everything up in Solidworks and got some prototypes made!
Head over to www.shapeways.com to see about their rapid prototyping server - its really fast, easy to use and mighty cheap.
Here are a couple of photos of the prototypes, first one is a ’simplified’ complete model and the second is the actual motor mount.
Unfortunately I had to change motor, so I have redesigned everything… But there was a special offer on at shapeways, so I was able to order more prototypes. This time I have also ordered parts which will be used on the final mouse including skids and sensor mounts.
My home (btw - Microdirect suck)
by Martyn on Sep.23, 2008, under Randomness
Thought I would post a quick picture of my desk, its quite a state atm; but is quite a pleasant place to work. And the light is usually that high, its very bright so I keep it out of direct sight. (Click of larger image)
I got my PC down on the right behind the chair, its 2.2ghz, 4gig RAM, and at the moment running Vista and Debian (I am working on some software for a client running linux). To the left of my monitor is my EEE PC 701, basically an email terminal, but also run IM and do random research on there. I am running synergy which allows me to move mouse and keyboard between the two, but have a spare mouse there still for some reason.
You can just see my 360 down on the right, there is a KVM switch on the floor (so I can switch using my foot!) and my current electronics project on the left of the desk. And the rest is random equipment / books / rubbish
Oh and microdirect suck, put an order in for a new router last Thursday (current router dies more often than I drink coffee, and I drink a lot of coffee), paid for next working day delivery. Ok, so I put the order in at midnight, but 1 working day after Friday is Monday, and with 2 non-working days in between Monday is a good guess, wrong, its late on Tuesday and its not here yet
Long live ebuyer !!!




