Sunday, October 18, 2009

Made my own offline picdelay calculator

I made my offline version of www.golovchenko.org/cgi-bin/delay
that should work for up to 1 year delay on a PIC which should
be enough for ordinary people. If you don't like it, you can change
the source! There is a discrepancy on 31536000 seconds output,
and I contacted the original author.
It mostly works the same, especially on small numbers, but on one year
delay his page gets d1 as 0x4D, me, I get 0x4E.
Also, the final cycles he needs 8+4, I need 6+4.
When I do the hand calculations with his numbers, the number of inner
cycles is 157679999999977 instead of 157679999999988 that his page states.



/* picdelay.c
usage: gcc picdelay.c; ./a.out
Generates source code for delay up to 1 year on <20MHz PIC ucontrollers
Mimics output of www.golovchenko.org/cgi-bin/delay

License: Public Domain by me,
the Anonymous Author@kolomp.blogspot.com
No contact info, so I don't get bothered with spam.
Hope you enjoy it.
*/


#include <stdio.h>

int main(void) {

long double mhz, delay_s, act_delay_s;
unsigned long long int totalcycles, ncycles, dummy;
unsigned char d[8], i, nvars;
//d[8], 256^8 > 365*24*60*60 secs * 20 MHz/4 cycles, max prog limit
//needs to be changed for longer delays/faster chips

printf("Delay seconds: "); scanf ("%Lf", &delay_s);
printf("Clock MHz: "); scanf ("%Lf", &mhz);

totalcycles=1e6/4*mhz*delay_s;
act_delay_s = (long double)totalcycles/mhz*4/1e6;

ncycles=totalcycles-4-1; //to include for "call" and last goto instructions

nvars=0; dummy=1;
while(dummy<ncycles)
{ nvars++; dummy = dummy*256*(2*nvars+1)/(2*nvars-1);}
//number of repeated instruction lines 2*nvars+1
//printf("dummy=%llu\n", dummy);

for(i=nvars;i>0;i--)
{ dummy = dummy/256;
d[i]=ncycles/dummy;
ncycles = ncycles % dummy;
//if (i>1)
// printf("d%d = 0x%X\n", i, d[i]+1);
//else
// printf("d%d = 0x%X\n", i, d[i] );
}
//ncycles left over, ex. on a 7 instruction loop the remainder could be 0,1,2,3,4,5,6
//add the 1 that the last goto misses
ncycles++;
//printf("ncycles=%d", ncycles);


//printf(" Delay seconds: %Lf seconds\n", delay_s);
//printf(" Clock frequency: %Lf MHz\n", mhz);
printf("; Actual delay = %.16Lf seconds %llu cycles\n", act_delay_s, totalcycles);
printf("; Error = %.16LF % \n", (1-act_delay_s/delay_s)*100);
printf("\n");
printf(" cblock\n");
for (i=1;i<nvars+1;i++)
printf(" d%d\n",i);
printf(" endc\n");
printf("\n");
printf("Delay\n");
printf(" ;%llu cycles\n",totalcycles-4-ncycles);
printf(" movlw 0x%X\n", d[1]);
printf(" movwf d1\n");
for (i=2;i<nvars+1;i++)
{ printf(" movlw 0x%X\n", d[i]+1);
printf(" movwf d%d\n",i);
}
printf("Delay_0\n");
for (i=1;i<nvars;i++)
{ printf(" decfsz d%d, f\n",i);
printf(" goto $+2\n");
}
printf(" decfsz d%d, f\n", nvars);
printf(" goto Delay_0\n");
printf("\n");
printf(" ;%d cycles\n", ncycles);
for (;ncycles>1;ncycles=ncycles-2)
printf(" goto $+1\n");
if (ncycles>0)
printf (" nop\n");
printf("\n");
printf(" ;4 cycles (including call)\n");
printf(" retlw 0; \n");

return 0;
}

No comments:

Post a Comment