Posted: 11:37pm 20 Jun 2016 |
Copy link to clipboard |
Print this post |
|
Prompted by a PM about the DMX protocol I've written a very simple CSUB that can generate any arbitrary sequence of bits.
Usage is simplicity itself:
Set up the pin as an output and set it to the required initial condition high or low
set up an array of bit lengths in micro-seconds expressed as floating point numbers
call the bitbanger CSUB
At the end of each bit duration the CSUB will invert the output so you need to specify both the on and off durations.
The CSUB takes care of things like CPU speed but of course the faster the CPU the more accurate the bit lengths
If an even number of bits is specified the output is left in the same state as it started. An odd number will result in it ending up inverted. In both cases the last duration specified does not result in a transition but must be included to terminate the CSUB
The picture is the result of the example code
Option explicit
option default NONE
setpin 19,DOUT
pin(19)=1
dim float lengths(9)=(1, 1.5, 0.5, 0.75, 1, 0.5, 1.5, 1, 0.5, 1) 'array of bit lengths in usec
pause 3000
bitbanger(19,10,lengths())
end
CSub bitbanger 'pin number, number of bits, floating point array of bit lengths in usec
00000000
27BDFFC0 AFBF003C AFBE0038 AFB70034 AFB60030 AFB5002C AFB30024 AFB20020
AFB1001C AFB00018 AFB40028 3C109D00 8E030000 00808821 8E020080 8C640000
00A09021 00002821 00C0B021 0040F809 8E140064 00409821 8E02009C 3C0449F4
0040F809 24842400 00402821 0280F809 02602021 0040B821 8E240000 8E020024
24050007 0040F809 241E0001 AFA20010 8E020028 0040F809 8E240000 8E520000
8E030040 005EF004 0060F809 00122080 AFA20014 12400013 0040A821 0000A021
00008821 3C139D00 0014A080 02D41821 8C640000 8E620058 8E70007C 0040F809
02E02821 26310001 0200F809 00402021 02B4A021 0232182B AE820000 1460FFF2
0220A021 8FA30014 3C040008 8C620000 2442FFFD AC620000 3C03BF88 AC641064
3C03BF88 00001021 AC601068 40824800 8FA50014 8FA30010 2652FFFF AC7E0000
8CA40000 00442021 40024800 0044182B 1460FFFD 00000000 1640FFF6 24A50004
8FBF003C 3C020008 3C03BF88 AC621064 3C03BF88 8FBE0038 8FB70034 8FB60030
8FB5002C 8FB40028 8FB30024 8FB20020 8FB1001C 8FB00018 AC621068 03E00008
27BD0040
End CSub
C source
void bitbanger(long long *mypin,long long *numpulses, float parray[]){
float ppusec=FDiv(IntToFloat(CurrentCpuSpeed),LoadFloat(0x49F42400));//number of clock ticks per microsecond
unsigned int volatile * invport=GetPortAddr(*mypin, LATINV);
int k,pin=1<<GetPinBit(*mypin);
register unsigned int index=0,next_clock,current_ticks = 0, j=*numpulses;
int *sarray=GetTempMemory(j * 4);
for(k=0;k<j;k++){
sarray[k]=FloatToInt(FMul(parray[k],ppusec));
}
sarray[0]=sarray[0]-3; //loop initialisation overhead
mT4IntEnable(0);
asm volatile("mtc0 %0, $9": "+r"(current_ticks)); //set the current number of ticks to 0
do {
*invport=pin;
next_clock=current_ticks+sarray[index++];
j--;
do {
asm volatile("mfc0 %0, $9" : "=r"(current_ticks));//get the time in ticks since zeroed
} while(current_ticks<next_clock);
} while(j);
mT4IntEnable(1); //re-enable the RTC
}
Edited by matherp 2016-06-22 |