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 : ArmMiteF4 BITBANG BITSTREAM Operation
Author | Message | ||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
Using the ArmmiteF4 with MM V5.07.02b2. @phil99 coded NECSend for the Picomite using MM. Const IRpin = MM.Info(pinno gp1) 'output pin, change as needed SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output Do 'Your program here. Input "Enter Device and Key codes "; dev, key NECsend IRpin, dev, key Loop Sub NECsend IRpin As integer, dev As integer, key As integer Local integer word, d(2200), m, n = 1 word = (dev<<16) + (key<<8) + ((255 Xor key )And 255) 'assemble 32 bits Math set 13 , d() '13=1000/(38*2)uS duration of a half cycle @ 38kHz d(672) = 4500 'pause after start pulse train For m = 714 To 2100 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) And 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next Device bitstream IRpin, 2199, d() 'send the data Pause 100 Pin(IRpin) = 0 End Sub This works for an Onkyo receiver. (Also with 'Device'command replaced with Bitbang) The above code with the IRpin changed to (pinno PE0} on the ArmmiteF4 does not work. After investigation it appears that "d(672) = 4500 'pause after start pulse train" is not interpreted by BITSTREAM. It shows up in the d(0) to d(800) bitstream exactly the same as the picomite but does not result in the 4.5mS space after the leading pulse burst. test values are devicecode 19832 keycode 192. Picomite ArmmiteF4 Tony |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
That is odd. I will test on an F4 tomorrow, getting a bit late now. Your scope pics indicate all the bitstream array index values are off by 1 anyway. It doesn't affect anything I have but I will tidy it up anyway. |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4280 |
Phil, There is more that is weird. The bursts are 42 cycles of 13us = 546us (not exacly 562, but close) The pauses between the bursts must be 562us (logic 0) -or- 1686us (logic 1). Look at both scope plots. Either the burst timing is wrong, or the pause timing is wrong. Visually there is simply too much burst visible. Checkif a single cycle is 13+13=26us. It feels the burst is 800us, in which case 13us is more 20us, 38kHz is 25kHz. Volhout P.S.... this feels like a job for PIO. Shift the 32 bit NEC value in FIFO, and let PIO do it's job. But I guess this is for the F4. No PIO. Volhout Edited 2024-03-21 23:47 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
It seems the F4 Bitbang Bitstream won't accept times greater than 3000uS so the 4500uS value gets corrupted. So something seems to be wrong. Also the modulation frequency is a little higher (39.8kHz) than for the Pico so the duration of the half-cycles has been increased from 13 to 14uS. Now it is a little low but close enough. The apparently wrong timing pointed out by Volhout are correct on my scope and the Sub works on my devices. Perhaps a display artefact in the images? 'Work-around for problems with Bitbang Bitstream on F4 Const IRpin = MM.Info(pinno PA0) 'output pin, change as needed SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output Do 'Your program here. NECsend IRpin, dev, key Loop Sub NECsend IRpin As integer, dev As integer, key As integer 'Version for ARMmite F407 MMBasic Version 5.07.02b2 Local integer word, d(1389), m, n = 1, c(671) word = (dev<<16) + (key<<8) + 255-key 'assemble 32 bits Math set 14 , c() '13=1000/(38*2)uS duration of a half cycle @ 38kHz 9mS start burst Math set 14 , d() '13=1000/(38*2)uS duration of a half cycle @ 38kHz main bitstream BitBang bitstream IRpin, 670, c() 'send 9ms start 38kHz Pause 1.5 '4.5mS pause after start pulse train - allowing for 3mS processing delays @ 168MHz CPU For m = 43 To 1387 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) AND 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next BitBang bitstream IRpin, 1387, d() 'send the data Pin(IRpin) = 0 End Sub Footnote added 2024-03-22 15:02 by phil99 Missed a line in the Do Loop. Input "Enter Device and Key codes "; dev, key As per the first version. |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
Hi Phil99, Thanks for this. I will give it a run shortly. Looking at the display resolution, I think this is the cause of the broad pulses. Having tried various values for 4.5ms pause I believed the problem was in the MMBasic coding for the F4. This is a great sub that is easy to use compared to getting a CSub to work. |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
Updated PicoMite version Sub NECsend IRout As integer, dev As integer, key As integer 'Picomite V5.08.00 version Local integer word, d(2066), m, n = 1 word = (dev<<16) + (key<<8) + 255-key '32bit word = Device 16b + Key 8b + inverted Key 8b Math set 13, d() 'fill array with half-cycles, 13uS = duration of a half cycle @ 38kHz d(691) = 4500 'uS pause after 9mS of 38kHz to start For m = 733 To 2065 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) And 1)*2 + 1) * 562.5'convert bits to pauses (0=562uS, 1=1687uS) Inc n 'step to next data bit Next Device bitstream IRout, 2066, d() 'send the data Pin(IRout) = 0 End Sub |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
A more accurate way to get the 4.5mS pause. The other was dependant on the CPU speed of the F4. Do 'Your program here. Input "Enter Device and Key codes "; dev, key NECsend IRpin, dev, key Loop Sub NECsend IRpin As integer, dev As integer, key As integer 'Version for ARMmite F407 MMBasic Version 5.07.02b2 Local integer word, d(1389), m, n = 1, c(671) word = (dev<<16) + (key<<8) + 255-key 'assemble 32 bits Math set 14 , c() '13=1000/(38*2)uS duration of a half cycle @ 38kHz Math set 14 , d() '13=1000/(38*2)uS duration of a half cycle @ 38kHz BitBang bitstream IRpin, 670, c() 'send 9ms start 38kHz Timer =0 For m = 43 To 1387 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) AND 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next Do : Loop Until Timer > 4.3 BitBang bitstream IRpin, 1387, d() 'send the data Pin(IRpin) = 0 End Sub Edited 2024-03-22 15:24 by phil99 |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
Hi phil99 Perfect! Thanks, Tony |
||||
disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 905 |
There is a couple of problems with F4 BITBANG. Its currently 21/20 too fast and wraps around when you ask for greater than 65565/20 uS. I will try to fix and post an update. Regards Gerry Latest F4 Latest H7 |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
Thankyou for such prompt attention. Not serious issues as there are simple ways to cope with both. Yet another revision. Array c() is unnecessary. Do 'Your program here. Input "Enter Device and Key codes "; dev, key NECsend IRpin, dev, key Loop Sub NECsend IRpin As integer, dev As integer, key As integer Local integer word, d(1389), m, n = 1 word = (dev<<16) + (key<<8) + 255-key 'assemble 32 bits Math set 14 , d() '13=1000/(38*2)uS duration of a half cycle @ 38kHz BitBang bitstream IRpin, 670, d() 'send 9ms start 38kHz Timer =0 For m = 43 To 1387 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) AND 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next Do : Loop Until Timer > 4.3 BitBang bitstream IRpin, 1387, d() 'send the data Pin(IRpin) = 0 End Sub Edited 2024-03-22 17:09 by phil99 Footnote added 2024-03-24 07:25 by phil99 In the event that the program using the NECsend Sub is also using the Timer odd things may hapen when the Sub resets it. These mods fix that. T = Timer + 4.3 For ... Next Do : Loop Until T < Timer Footnote added 2024-03-24 07:30 by phil99 Also add this line. Local Float T |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4280 |
Yes ! Smart use of d(). Very good. Also memory efficient. Not waste time, build the d() array while waiting for 4.5ms (4.3) to pass. Smart. Volhout Edited 2024-03-22 20:12 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
@phil99 thanks for getting this going. @disco4now will monitor for your input. Thanks for your work on the F4. I have several sitting around as I stopped using them when it became a problem it the battery failed. Now am dusting them off and having fun. Regards Tony |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
It is a bit fiddly to do but you can replace the cell holder with a CR2032 one. Lasts much longer. |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
Here is code that incorporates bit reversing as NEC protocol is LSB bit first. This means that the ARMmiteF4 device and key codes match that of the Micromite. '22/3/2024 - new NECSend routine to replace original due problem with 4.5mS space generation ' modified to use same dev code and key code as micromite ' IR Transmit Const IRpin = MM.Info$(pinno PE0) 'output pin, change as needed SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output ' IR receiver input, fixed as PE2 for F4 ' Do 'Your program here. Input "Enter Device and Command codes "; devin, keyin ConvInput ' use function revb to reverse bits in a word as NEC IR code sent LSB first NECsend IRpin, DevCode, KeyCode pause 1000 Loop Sub NECsend IRpin As integer, dev As integer, key As integer Local integer word, d(1389), m, n = 1 word = (DevCode<<16) + (KeyCode<<8) + 255-KeyCode 'assemble 32 bits Math set 14 , d() '13=1000/(38*2)uS duration of a half cycle @ 38kHz BitBang bitstream IRpin, 670, d() 'send 9ms start 38kHz Timer =0 For m = 43 To 1387 Step 42 'load data after start sequence d(m) = (((word>>(32-n)) AND 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next Do : Loop Until Timer > 4.3 BitBang bitstream IRpin, 1387, d() 'send the data Pin(IRpin) = 0 End Sub '----------------------------- sub ConvInput ' use function revb to reverse bits in a word as NEC IR code sent LSB first 'Check if device code is 8 bit or 16 bit If devin < 256 Then ' 8 bit address, so add inverse of address DevCode=(revb(devin,8)<<8) + 255-(revb(devin,8))'add inverse to form 16 bits Else ' extended or 16 bit address DevCode=revb(devin,16) end if KeyCode=revb(keyin,8) print "Input- device ";devin;" "; bin$(devin);" keyin ";keyin;" ";Bin$(keyin) print "Output- DevCode "; DevCode;" ";BIN$(DevCode,16);" ";" KeyCode ";KeyCode;" ";Bin$(KeyCode,8) end sub ' Function to reverse bits in byte as NEC IR code sent LSB first Function revb(x As integer, y As integer) As integer Local integer z revb=0 For z=1 To y 'select bit starting from RHS to LHS If x And (1<<(z-1)) Then revb=revb Or (1<<(y-z)) EndIf Next z End Function Also to read IR codes use: 'F4-NECRx-bit-reverse ' modified to use same dev code and key code as the micromite ' IR receiver input, fixed as PE2 for F4 ' IR dev, key , irint 'Rx.int 'start the decoder Print "Waiting for IR input" Do 'Your program here. pause 1000 Loop 'process detected IR input irint: If (dev And &HFF) = ((dev>>8) Xor &HFF) Then ' normal address Print "device address 8 bit " DevCode=revb((dev>>8),8) KeyCode=revb(key,8) Else ' extended address Print "device address 16 bit " DevCode=revb(dev,16) KeyCode=revb(key,8) EndIf 'print "device ";dev;" "; bin$(dev,16);" command ";key;" ";Bin$(key,8) print "DevCode ";DevCode," "; bin$(DevCode,8);" KeyCode ";KeyCode;" ";Bin$(KeyCode,8) IReturn ' Function to reverse bits in byte as NEC IR code sent LSB first Function revb(x As integer, y As integer) As integer Local integer z revb=0 For z=1 To y 'select bit starting from RHS to LHS If x And (1<<(z-1)) Then revb=revb Or (1<<(y-z)) EndIf Next z End Function Tony |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
I guess the bit reversal could be incorporated in the NECsend sub but the Dev and Key codes I used for testing are from the built-in IR Receive function. They work on all my devices without reversing. Perhaps the output of that is already reversed. When Gerry / @disco4now gets Bitstream fixed just change:- Math set 14, d() back to Math set 13, d() The split Bitstream should still work without change. |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
It's a compatibility thing. The reason I did it was so that it gives the same device and key codes for the NECSend (and NEC receive) as the MX170 Micromite code gives. |
||||
phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 2155 |
Some other bit reversal options in this thread. This one is very clever. > b%=73 : ? bin$(b%,8) 01001001 > Rb% = (b% * &H0202020202 and &H010884422010) mod 1023 > ? bin$(Rb%,8) 10010010 > Footnote added 2024-03-25 07:16 by phil99 Using the above on a 16 bit device code. > b% = 54321 : ? bin$(b%,16) 1101010000110001 > Rb% = (((b% and 255) * &H0202020202 and &H010884422010) mod 1023) << 8 > Rb% = Rb% + ((b% >> 8) * &H0202020202 and &H010884422010) mod 1023 > ? bin$(Rb%,16) 1000110000101011 > Footnote added 2024-03-25 07:22 by phil99 Or this. > b% = 54321 : ? bin$(b%,16) 1101010000110001 > Rb% = (((b% and 255) * &H0202020202 and &H010884422010) mod 1023) << 8 > inc Rb%, ((b% >> 8) * &H0202020202 and &H010884422010) mod 1023 > ? bin$(Rb%,16) 1000110000101011 > |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
Very interesting. Time to look at doing it better. TBS is a great resource. It's a long time since I have done any programming. |
||||
morgs67 Regular Member Joined: 10/07/2019 Location: AustraliaPosts: 76 |
Tuned up with reversal code mentioned above. Device and key code match original micromite input and output codes. Transmit- 'Using 'Bit Twiddling Hacks' (Search on the Internet) pointed to by phil99 ,matherp '22/3/2024 - new NECSend routine to replace original due problem with 4.5mS space generation 'uses the same dev code and key code as the micromite ' IR Transmit Const IRpin = MM.Info$(pinno PE0) 'output pin, change as needed SetPin IRpin, dout : Pin(IRpin) = 0 ' IR code output ' IR receiver input, fixed as PE2 for F4 ' Do 'Your program here. Input "Enter Device and Command codes "; dev, key NECsend IRpin, dev, key pause 1000 Loop Sub NECsend IRpin As integer, dev As integer, key As integer Local integer word, d(1389), m, n = 1 'need to reverse bits in a byte as NEC IR code is sent LSB first If dev < 256 Then ' 8 bit address, so add inverse of address DevCode = ((dev * &H0202020202 and &H010884422010) mod 1023)<<8 DevCode = DevCode + (255-((dev * &H0202020202 and &H010884422010) mod 1023)) Else ' extended or 16 bit address DevCode = (((dev and 255) * &H0202020202 and &H010884422010) mod 1023) << 8 DevCode = DevCode + ((dev>> 8) * &H0202020202 and &H010884422010) mod 1023 end if KeyCode = (key * &H0202020202 and &H010884422010) mod 1023 'Check operation of bit reverse code print "Input- device ";dev;" "; bin$(dev);" key ";key;" ";Bin$(key) print "Output- DevCode "; DevCode;" ";BIN$(DevCode,16);" ";" KeyCode ";KeyCode;" ";Bin$(KeyCode,8) ' word = (DevCode<<16) + (KeyCode<<8) + 255-KeyCode 'assemble 32 bits to transmit ' Math set 14 , d() '14=1000/(38*2)uS duration of a half cycle @ 38kHz BitBang bitstream IRpin, 670, d() 'send 9ms start 38kHz Timer =0 For m = 43 To 1387 Step 42 'load data sent after start sequence d(m) = (((word>>(32-n)) AND 1)*2 + 1) * 562.5 'convert bits to duration (short = 0, long = 1) Inc n 'step to next data bit Next Do : Loop Until Timer > 4.3 'send 4.5ms start space BitBang bitstream IRpin, 1387, d() 'send the data Pin(IRpin) = 0 End Sub IR received decoder- 'Using 'Bit Twiddling Hacks' (Search on the Internet) pointed to by phil99 ,matherp 'uses the same device code and key code as the micromite 'IR receiver input, fixed as PE2 for F4 foreCol% = RGB(white) backCol% = rgb(BLACK) CLs IR dev, key , irint 'start the decoder Print " Waiting for IR input" text 1,20," Waiting for IR input",LT,1,1,foreCol%,backCol% Do 'Your program here. pause 1000 Loop 'IR input detected irint: If (dev And &HFF) = ((dev>>8) Xor &HFF) Then ' 8 bit address Print "device address 8 bit " DevCode = ((dev>>8) * &H0202020202 and &H010884422010) mod 1023 Else ' extended or 16 bit address Print "device address 16 bit " DevCode = (((dev and 255) * &H0202020202 and &H010884422010) mod 1023) << 8 DevCode = DevCode + ((dev>> 8) * &H0202020202 and &H010884422010) mod 1023 EndIf KeyCode = (key * &H0202020202 and &H010884422010) mod 1023 ' print "DevCode ";DevCode," "; bin$(DevCode,8);" KeyCode ";KeyCode;" ";Bin$(KeyCode,8) cls text 1,20,"Device Code:"+STR$(DevCode)+" Key Code:"+STR$(KeyCode),LT,1,1,foreCol%,backCol% ' IReturn Tony Footnote added 2024-06-06 17:00 by morgs67 Update for transmit code: Footnote added 2024-03-24 07:25 by phil99 In the event that the program using the NECsend Sub is also using the Timer odd things may hapen when the Sub resets it. These mods fix that. T = Timer + 4.3 'Replaces Timer = 0 For ... Next Do : Loop Until T < Timer 'Replaces Do : Loop Until Timer > 4.3 Also add this line. Local Float T |
||||
Print this page |