PDA

View Full Version : Is it possible to interpret non-standard serial data with PicBasic (sample attached)



CuriousOne
- 7th July 2016, 14:04
I have some remotely managed studio strobe, it has keyboard, and when pressing numerical keys, the following sequences being transmitted on single wire, as shown on the picture. What protocol is this, and can I somehow interpret it, using picbasic pro?

http://i.imgur.com/1QPLqSU.jpg

Width of wide pulse is 1.9msec, and width of narrow pulse is 642usec.

Dave
- 7th July 2016, 15:54
It looks like some kind of binary coding judging by the number entered and the output stream. Why not ask the manufacture for the protocol?

Heckler
- 7th July 2016, 16:05
hi dave,

it reminds me of a sort of binary encoding...
0= no missing pulse 0000
1= 1 missing pulse in the "ones" position 0001
2= 1 missing pulse in the "twos" position 0010
3= ones missing and twos missing 0011
4= 1 missing pulse in the fours position 0100
5= ones and fours missing 1001

it would help to see all the way up to 9
do you also need to decode other letter/function key/enter/backspace etc. etc. characters??

I don't recognize the protocol off hand but then I am no protocol expert.

perhaps some sort of digital logic analyzer that has a good interpreter behind it would help.
something like this... https://www.saleae.com
I have never used the saleae but I know it comes highly regarded for it's price.

good luck

CuriousOne
- 7th July 2016, 16:25
Yes is goes up that way, I can record it up to 9, but you are correct, it looks like plain BCD code, but the rendering of "0" and "1" with pulses, looks weird for me. I have saelae logic analyzer, but it can't detect these pulses at all, I've used scope to record them.

In fact, I want very simple thing - say, set variable ENABLE=0, when "zero" is transmitted, and ENABLE=1, when any other digit is being sent. I'm not looking for character decoding or whatsoever.

CuriousOne
- 7th July 2016, 18:05
I was suggested, that this is PPM (Pulse Position Modulation), used in some IR/RF remotes and telemetric control equipment. Datasheet of Holtek HT6222 shows quite similar, but not exact diagram of signal.

pedja089
- 7th July 2016, 18:39
If you need only ENABLE use count to count pulses.
Try something like this:


COUNT Pin, Period, Var
If Var<xxx then
enable=1
else
enable=0
endif

CuriousOne
- 8th July 2016, 05:33
But pulses are of different width in series, will it work?

CuriousOne
- 8th July 2016, 11:50
Just checked, it works, but not as it should - even on same sequence, it always reads different values.



taki:
COUNT PORTC.4, 70, LABEL
if label=0 then
goto taki
endif
LCDOUT $FE,$c0, DEC(LABEL), " "
PAUSE 5
GOTO TAKI

pedja089
- 8th July 2016, 12:12
try this:
taki:
While PORTC.4=0
WEND
COUNT PORTC.4, 70, LABEL
LCDOUT $FE,$c0, DEC5 LABEL
PAUSE 5
GOTO TAKI

CuriousOne
- 8th July 2016, 12:36
The actual issue is different I guess.

The system used is IDPPM - Differential Pulse Position Modulation.
Now I changed algorithm, and it detects pulses, there are 34 pulses, and it does it properly. But quantity of pulses is always 34, only pauses between them change, so COUNT is not proper implementation I guess.

P.S. above code displays only 00000

pedja089
- 8th July 2016, 12:54
I was thinking that 1 is represented with missing pulse.
You can try something like this

DEFINE PULSIN_MAX 65535 ' Limit wait-for-pulse and maximum-pulse count
While PORTC.4=0 'wait for rising edge of start pulse
WEND
FOR I=0 TO 33
PULSIN PORTC.4,0,W3
IF W3>XXX THEN GOTO GotData
NEXT I

CuriousOne
- 8th July 2016, 13:18
A side note, a statement like

IF PORTC.4=1 THEN

actually sets PORTC.4 high.

Is this bug or feature?

I've added 1 transistor signal inverter, but no help. Also, your code does not work.

OK, I will give up with this idea.

Heckler
- 8th July 2016, 15:08
This, to me, is the classic problem of how to tell (program) your micro controller to recognize and interpret the pattern.
The human brain combined with an eyeball can recognize it... now you just need to figure out how to translate that into code.

I would start by watching for the start pulse, which is longer than the other pulses. Then keep track of the width of the following pulses (or the width of the "low" part. Then watch for one or more extended "low" pulses.

Since you only need to differentiate between 0 and any other number/key press, then just watch for an extended "low" in a given time period after the extended "high" start pulse. If in the given time period you do not get any extended "low" pulses then the digit is "0" other wise if you get an extended "low" pulse then the keypress was non-zero.

Since the quantity of pulses in each character is always 34 then you should be able to just set up a counter to increment whenever the pulse is low and stop incrementing when the pulse goes back high. Then if the counter has incremented above a certain threshold then that particular "low" pulse was a "wide" one and indicates a non zero digit. (I hope that makes sense)

I believe it is easily do-able. you just need to distill it down to how to detect the extended low pulse that indicates a non-zero digit pressed.

that is how I would attack the challenge.

pedja089
- 8th July 2016, 15:44
Code for that is in post #11 except it waits for transition from low to high to start measure 34 low intervals.

CuriousOne
- 8th July 2016, 16:44
Yes, I know how to implement detection logically, I have no issues with algorithm, but I can't implement it in hardware, also, I can't understand, why statement
IF PORTC.4=1

or

IF PORTC.4=0

makes corresponding pin high or low?

tumbleweed
- 8th July 2016, 17:41
IF PORTC.4=1
or
IF PORTC.4=0

makes corresponding pin high or low?
I highly doubt that. I don't know how you're testing it, but if that's the case things are seriously broken.

You likely have some other issue.

HenrikOlsson
- 8th July 2016, 18:57
The IF statement per se should not and I'm pretty sure does not twiddle the pin but if what you you're doing is somehing like...

If PortC.4 = 0 THEN
PortC.1 = 1
ENDIF

...and there happens to be analog functions on the pins which you haven't disabled then the actual state of PortC.4 isn't read correctly and you're getting into the classic RMW issue where the "invalid" state of PortC.4 is being written back to PortC.4 when the write operation to PortC.1 occurs but without seeing the rest of the code it's hard to say for sure.

/Henrik.

CuriousOne
- 8th July 2016, 20:20
Here is the complete code:



Include "modedefs.bas" ' Include serial modes
TRISA = %11111111 ' Set PORTA to all input
TRISC = %00000000 ' Sets all PortB pins to output
ADCON1 = %10000101 ' Set PORTA analog and right justify result
ADCON0=%00000000
low portc.4
low portc.5

X VAR PORTC.4

DEFINE LCD_DREG PORTB
DEFINE LCD_DBIT 4
DEFINE LCD_RSREG PORTB
DEFINE LCD_RSBIT 0
DEFINE LCD_EREG PORTB
DEFINE LCD_EBIT 1
DEFINE LCD_BITS 4
DEFINE LCD_LINES 2
DEFINE LCD_COMMANDUS 1500
DEFINE LCD_DATAUS 44
DEFINE OSC 4

lcdout "test 2"
PAUSE 500

LABEL VAR WORD
DROEBITI VAR WORD


taki:
if portc.4=0 then
COUNT PORTC.4, 60, LABEL
endif
if label=0 then
goto taki
endif
LCDOUT $FE,$c0, DEC(LABEL), " "
GOTO TAKI


I have source of signal (chip with name grinded off, but holtek logo is recognizable), which is connected directly to PORTC.4. Also, scope is connected to same pin.

As long as I introduce the statement "if portc.4=0 then"
If it is "=0" then pin is sunk to ground, so no pulses can be detected, and nothing can be seen on scope. If it is "=1", then pin gets driven high, and no pulses can be seen with scope or read too.

Chip is 16F870.

pedja089
- 8th July 2016, 21:40
TRISA = %11111111 ' Set PORTA to all input
TRISC = %00000000 ' Sets all PortB pins to output
ADCON1 = %10000101 ' Set PORTA analog and right justify result
ADCON0=%00000000
low portc.4
low portc.5

Is there something strange here?

Art
- 9th July 2016, 13:53
Easy! It’s giving you a wider pulse duration at the start to qualify the incoming data.
From there you only need to sample 32 times at the correct interval.
So look for that, then read it in with a 32 step loop.




bitcode var byte[32]
count var byte
pulseduration var byte

pulseduration = time from peak to peak

for count = 0 to 31
bitcode[count] = inputpin
pause pulseduration
next count


Of course, better ways than reading into a 32 byte array, but quickest.

CuriousOne
- 9th July 2016, 14:13
You're omitting an important thing - MCU has own clock, wastes different time on program execution, but incoming data is sent async, so it can't wait for MCU to become ready, so my guess, how it all should work, is as follows:

As pulse arrives, we start recording it as fast as possible, after pulse sequence finished, we just count numbers of 1's and 0's recorded, and based on that, decide what to do with decoded data. Considering total sequence duration and speed, I guess, external sram or eeprom might be needed?

Art
- 9th July 2016, 14:48
That depends. You didn’t display the duration.
If it’s several uS duration pulses, the falling edge of the first longer pulse is the place to mark time,
then waste half a pulse duration before the for-next loop. If you can roughly synchronise from the first pulse (which is what it’s for),
it takes time for the two clocks to drift apart.

If you were to sample bits as fast as you can, you’d still want to do that from the falling edge of the first pulse.

Art
- 9th July 2016, 14:57
Does your hardware have the LCD that is in your code?

Art
- 9th July 2016, 15:26
That should get the 32 bits straight into a four byte array.



'
main:
@ clrwdt
'
if portc.4 = 1 then ‘ count initial pulse duration
leadcnt = leadcnt + 1
else
leadcnt = 0
endif
'
'
if leadcnt > expectedduration then' qualify initial pulse duration
burst: ' sync to initial pulse falling edge
if portc.4 = 1 then
@ clrwdt
goto burst
endif
'
for rotcnta = 0 to 3 ' shift data into 32 bit buffer
databuffer = 0
for rotcntb = 0 to 7 ‘ shift data to each byte
databuffer.bit0 = portc.4
databuffer = databuffer << 1
dataarray[rotcnta] = databuffer
pauseus peaktopeakduration
next rotcntb
next rotcnta

leadcnt = 0
endif
'
goto main

richard
- 9th July 2016, 15:36
surely a candidate for timer1 and gate control

CuriousOne
- 9th July 2016, 20:29
Currently I have LCD connected, for debugging purposes, but in final device, I will have no LCD.

CuriousOne
- 9th July 2016, 20:40
So this is how initial things should work, as I see it:

1. We sent interrupt on rising edge of PORTC.4
2. As PORTC.4 gets high, timer is started, and counts to predefined value (width of 1st pulse)
3. While timer is running, PORTC.4 is still being continuously checked, to determine, whenever it is still high. It should be high while timer is counting, if it gets low, while timer is on, this means, this is not proper pulse, so we should reset and start everything over.
4. If timer counting ended, and PORTC.4 was high all that time, this means that sync pulse was captured correctly, and we're ready for the next step.

This appears quite simple in words, but all Greek for me, in code :), so far, my practical experience with timers and pwm is light dimming, and playing polyphonic tunes via it :D

Ioannis
- 9th July 2016, 21:06
Or Timer1 and Interrupt on Change or even better Interrupt on PortB.0 and use of Option_reg.6 to select which edge is expected to arrive and trigger the interrupt.

Needs a bit of work in the interrupt routine...

Ioannis

CuriousOne
- 10th August 2016, 07:30
Indeed, but lack of knowledge.... :)

CuriousOne
- 4th September 2016, 19:17
Code that works - It differentiates "0" from any other command:



UIDEDA:

if pulsi=0 then
FOR N=0 TO 300 'main loop duration
IF PULSI=0 THEN
A=A+c 'count positive edges
c=0 'stop increasing 1 after first loop
d=1 'set increase for 0
ELSE
B=B+d 'count 0 volt
d=0 'stop increasing 0 after first loop
c=1 'set increase for 1
ENDIF
NEXT
IF A<>0 AND B<>0 THEN
lcdout $FE,2, "A=",#A, " "
lcdout $FE,$C0,"B=",#B, " "
ENDIF
if a=7 and b=8 then high natura 'on
if a=6 and b=7 then low natura 'off
A=0
B=0
endif
GOTO UIDEDA

CuriousOne
- 4th September 2016, 19:35
Now I want to ad an array, where, when "1" occurs, value of N variable will be stored, which later can be counted, and position of "1" s and "0" -s detected.

CuriousOne
- 6th October 2016, 10:48
Going totally crazy, can't figure out what to do and how :(

CuriousOne
- 6th October 2016, 15:51
Logically, code should look like this:

WAIT FOR LOW LEVEL AND MEASURE IT'S DURATION
IF LOW LEVEL LENGTH=10MS THEN MEASURE HIGH LEVEL DURATION AFTER IT
IF HIGH LEVEL DURATION WAS 2MS, THEN GO TO NEXT STEP, ELSE, LOOP THIS CYCLE AGAIN
NEXT LEVEL:
CONSIDER 600US LOW LEVEL AS 1, AND 2MS LOW LEVEL AS 0, WRITE THEM SEQUENTALY TO 32 BIT ARRAY, UNTIL 32 BITS WRITTEN
EXTRACT MSB AND LSB FROM ARRAY
CONVERT TO WORD

CuriousOne
- 6th October 2016, 17:56
Or, more "programmer" approach. Assuming "A" is the input pin:

START COUNTING
A=0, B=0
WHILE A=1, B=B+1
WHILE A=0, C=C+1
IF B=500 AND C=100 THEN CONTINUE, ELSE, START OVER
B=0 C=0
FOR N=1 TO 32
WHILE A=1, B=B+1
WHILE A=0, C=C+1
IF B=50 AND C=50 THEN CONTENTS[N]=1
IF B=50 AND C=150 THEN CONTENTS[N]=0
A=0, B=0
NEXT N


8317

HenrikOlsson
- 6th October 2016, 18:05
Here's one idea:

HighTime VAR WORD
LowTime VAR WORD
BitArray VAR WORD [2]
LSB VAR BitArray.LowWord
MSB VAR BitArrat.HighWord

WaitForStartBit:
GOSUB MeasureLow
IF (LowTime < 9500) OR (LowTime > 10500) THEN WaitForStartBit ' 9.5-10.5ms qualifies
GOSUB MeasureHigh
IF (HighTime < 1500) OR (HighTime > 2500) THEN WaitForStartBit ' 1.5-2.5ms qualifies

NextLevel:
For i = 0 to 31
GOSUB MeasureLow
IF (LowTime > 400) AND (LowTime < 800) THEN BitArray.0[i] = 1 ' 500-700us qualifies as 1
IF (LowTime > 1700) AND (LowTime < 2320) THEN BitArray.0[i] = 0 ' 1800-2200us qualifies as 0
NEXT
LCDOUT $FE,$01, "HighWord", DEC MSB
LCDOUT $FE,$C0, "LowWord", DEC LCB

Pause 1000
Goto WaitForStartBit

MeasureLow:
LowTime = 0
While Signal = 1 : WEND ' Wait for low level
While Signal = 0 ' Measure low level
LowTime = LowTime + 100 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweak to calibrate, depends on actual loop time
WEND
RETURN

MeasureHigh:
HighTime = 0
WhileSignal = 0 : WEND ' Wait for low
While Signal = 1 ' Measure high level
HighTime = HighTime + 1 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweal to calibrate, depends on actual loop time
WEND
RETURN

I can't compile this let alone test it but it serves to show the genereal idea of a software only solution.

CuriousOne
- 6th October 2016, 20:20
Thanks, will give it a try tomorrow.

My oscilloscope can record in .csv format, is it possible in some emulator to "play back" this recording, and feed it to virtual chip? So I can test and debug without using original hardware, which generates these pulses.

richard
- 7th October 2016, 04:21
the waveform is simple to simulate like this is you have a chip with a dsp module.
note the timings are estimated since the curious one's info is lacking most of the meaningful detail


'************************************************* ***************
'* Name : MODULATOR.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 5/29/2016 *
'* Version : 1.0 *
'* Notes : *
'* : 16F1825 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG

OSCCON=$70
DEFINE OSC 32

' PIC 16F1825

TRISA = %111111 ' Make all pins Input
trisc = %101111 ;Make all pins Input
ANSELA=0
ANSELC=0
MDSRC= %00000000
MDCARH =%11000100
MDCARL =%00000000
X VAR byte
darta VAR byte[4]
TIMER1 VAR WORD EXT
clear
modout var latc.4
darta.0[15]=1
hpwm 1,128,1600
MDCON.0 = 0
modout =0
Main_Loop:
modout=1
pauseus 8000
modout =0
while tmr2 :wend
MDCON= %11000000
for x = 0 to 31
while tmr2 :wend
MDCON.0 = ! darta.0[x]
next
modout=1
MDCON= 0
pauseus 600
modout = 0
PAUSE 200
goto Main_Loop
end

richard
- 7th October 2016, 05:08
this works better the first one did no work for sequential 1's


'************************************************* ***************
'* Name : MODULATOR.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 5/29/2016 *
'* Version : 1.0 *
'* Notes : *
'* : 16F1825 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG

OSCCON=$70
DEFINE OSC 32

' PIC 16F1825

TRISA = %111111 ' Make all pins Input
trisc = %101111 ;Make all pins Input
ANSELA=0
ANSELC=0
MDSRC= %00000000
MDCARH =%11000100
MDCARL =%00000000
X VAR byte
darta VAR byte[4]
TIMER1 VAR WORD EXT
clear
modout var latc.4
darta.0[14]=1
darta.0[15]=1
hpwm 1,128,1600
MDCON.0 = 0
modout =0
Main_Loop:
modout=1
pauseus 8000
modout =0
while tmr2 :wend
MDCON= %11010001
for x = 0 to 31
while tmr2 :wend

if darta.0[x] then
MDCON.0 = 0
while tmr2 :wend
pauseus 6
while tmr2 :wend
pauseus 6
MDCON.0 = 1
while tmr2 :wend
pauseus 6
else
MDCON.0 = 1
endif
next
modout=1
MDCON= 0
pauseus 600
modout = 0
PAUSE 200
goto Main_Loop
end

richard
- 7th October 2016, 05:16
the output

CuriousOne
- 7th October 2016, 08:16
Wow! Such an input.

Here are signal details. Actual signal is high and goes low, on my last picture, I've inverted it just for ease of viewing and analyzing.

On the picture below, I've specified all timings as required.
8320

richard
- 7th October 2016, 08:40
8321
as close as I can get . it has a glitch after the last bit sent


'************************************************* ***************
'* Name : MODULATOR.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 5/29/2016 *
'* Version : 1.0 *
'* Notes : *
'* : 16F1825 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG

OSCCON=$70
DEFINE OSC 8

' PIC 16F1825

TRISA = %011111 '
trisc = %001111 ;
ANSELA=0
ANSELC=0
MDSRC= %00000000
MDCARH =%01000100
MDCARL =%00000000
X VAR byte
darta VAR byte[4]
TIMER1 VAR WORD EXT
clear
modout var latc.4
darta.0[14]=1
darta.0[15]=1
t2con=6
pr2=158
CCPR1L =318>>2
ccp1con=12
MDCON.0 = 0
modout =1
Main_Loop:
lata.5=1 ; cro trigger
while !pir1.1 :wend
modout=0
pauseus 9900
modout =1
pir1.1=0
while !pir1.1 :wend
pir1.1=0
while !pir1.1 :wend
MDCON= %11000001
pir1.1=0
while !pir1.1 :wend
for x = 0 to 31
if darta.0[x] then
MDCON.0 = 0
pir1.1=0
while !pir1.1 :wend
pir1.1=0
while !pir1.1 :wend
MDCON.0 = 1
pir1.1=0
while !pir1.1 :wend
else
MDCON.0 = 1
pir1.1=0
while !pir1.1 :wend
endif
next
modout = 1
MDCON = 0

lata.5=0
PAUSE 200
goto Main_Loop
end

CuriousOne
- 7th October 2016, 08:53
Thanks!

I guess, your code can run on 16F1829 ?

richard
- 7th October 2016, 09:39
I guess, your code can run on 16F1829 ?

should do they are the same except for a few extra pins

richard
- 7th October 2016, 12:01
well the dsp module is interesting but for this project perhaps its easier to do it the old way



'************************************************* ***************
'* Name : MODULATOR.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2016 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 5/29/2016 *
'* Version : 1.0 *
'* Notes : *
'* : 16F1825 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG

OSCCON=$70
DEFINE OSC 32



' PIC 16F1825



TRISA = %001111 ' Make some pins Input
trisc = %001111 ;Make some pins Input
ANSELA=0
ANSELC=0



X VAR byte
darta VAR byte[4]


clear

modout var latc.4
darta.0[14]=1
darta.0[15]=1


modout =1
lata.5=0 ;cro triger
Main_Loop:
lata.5=1
modout=0
pauseus 9900
modout =1
pauseus 1880
for x = 0 to 30
modout =0
if darta.0[x] then
pauseus 2000
else
pauseus 780
endif
modout =1
pauseus 635
next
modout =1
lata.5=0
PAUSE 200

goto Main_Loop
end

Art
- 9th October 2016, 04:48
Did you try code I posted a month ago, or looked at it to determine it won’t work?
It’s used in an IR remote receiver for a game controller (so has to be reliable)
to interpret exactly the same pulse coded signal, with the timings being the only difference.

CuriousOne
- 10th October 2016, 06:24
No, I haven't used it, because protocol is different from IR protocol.

CuriousOne
- 10th October 2016, 07:46
Just tried Henrik's code, it gives error on:

LSB VAR BitArray.LowWord

"bad variable size modifier .lowword"

CuriousOne
- 10th October 2016, 07:58
Corrected the errors, to level of my knowledge. Code compiles now, but it does not do anything. Here it is:



;----[16F1829 Hardware Configuration]-------------------------------------------
#IF __PROCESSOR__ = "16LF1829"
#DEFINE MCU_FOUND 1
#CONFIG
cfg1 = _FOSC_INTOSC ; INTOSC oscillator: I/O function on CLKIN pin
cfg1&= _WDTE_OFF ; WDT disabled
cfg1&= _PWRTE_OFF ; PWRT disabled
cfg1&= _MCLRE_OFF ; MCLR/VPP pin function is digital input
cfg1&= _CP_OFF ; Program memory code protection is disabled
cfg1&= _CPD_OFF ; Data memory code protection is disabled
cfg1&= _BOREN_OFF ; Brown-out Reset disabled
cfg1&= _CLKOUTEN_OFF ; CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin
cfg1&= _IESO_ON ; Internal/External Switchover mode is enabled
cfg1&= _FCMEN_OFF ; Fail-Safe Clock Monitor is disabled
__CONFIG _CONFIG1, cfg1
cfg2 = _WRT_OFF ; Write protection off
cfg2&= _PLLEN_OFF ; 4x PLL disabled
cfg2&= _STVREN_ON ; Stack Overflow or Underflow will cause a Reset
cfg2&= _BORV_19 ; Brown-out Reset Voltage (Vbor), low trip point selected.
cfg2&= _LVP_OFF ; High-voltage on MCLR/VPP must be used for programming
__CONFIG _CONFIG2, cfg2
#ENDCONFIG
#ENDIF
;----[Verify Configs have been specified for Selected Processor]----------------
; Note: Only include this routine once, after all #CONFIG blocks
#IFNDEF MCU_FOUND
#ERROR "No CONFIGs found for [" + __PROCESSOR__ +"]"
#ENDIF
DEFINE OSC 16
include "modedefs.bas"
ANSELA = %00000000 ' Set PORTA pins to digital I/O
ANSELB = %00000000 ' Set PORTB pins to digital I/O
ANSELC = %00000000 ' Set PORTC pins to digital I/O
WPUB = %00000000 'DISABLE WEAK PULL UP
TRISB=%11110000 'SET PORTB TO OUTPUT
TRISA=%00000000 'SET PORTA TO OUTPUT
TRISC=%00000000 'SET PORTC TO OUTPUT
OSCCON = %01111111 'SET INTOSC TO 16MHZ
' Set LCD Data port
DEFINE LCD_DREG PORTC
' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_DBIT 4
' Set LCD Register Select port
DEFINE LCD_RSREG PORTA
' Set LCD Register Select bit
DEFINE LCD_RSBIT 5
' Set LCD Enable port
DEFINE LCD_EREG PORTA
' Set LCD Enable bit
DEFINE LCD_EBIT 4
' Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 4
' Set number of lines on LCD
DEFINE LCD_LINES 2
' Set command delay time in us
DEFINE LCD_COMMANDUS 1500
' Set data delay time in us
DEFINE LCD_DATAUS 44
LCDOUT $FE, $C0, "TEST"
HighTime VAR WORD
LowTime VAR WORD
BitArray VAR WORD [2]
LSB VAR BitArray.lowbyte
MSB VAR BitArray.Highbyte
Signal var PORTB.6
i var word
WaitForStartBit:
GOSUB MeasureLow
IF (LowTime < 9500) OR (LowTime > 10500) THEN WaitForStartBit ' 9.5-10.5ms qualifies
GOSUB MeasureHigh
IF (HighTime < 1500) OR (HighTime > 2500) THEN WaitForStartBit ' 1.5-2.5ms qualifies

NextLevel:
For i = 0 to 31
GOSUB MeasureLow
IF (LowTime > 400) AND (LowTime < 800) THEN BitArray.0[i] = 1 ' 500-700us qualifies as 1
IF (LowTime > 1700) AND (LowTime < 2320) THEN BitArray.0[i] = 0 ' 1800-2200us qualifies as 0
NEXT
LCDOUT $FE,$01, "HighWord", DEC MSB
LCDOUT $FE,$C0, "LowWord", DEC LSB
Pause 1000
Goto WaitForStartBit
MeasureLow:
LowTime = 0
While Signal = 1 : WEND ' Wait for low level
While Signal = 0 ' Measure low level
LowTime = LowTime + 100 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweak to calibrate, depends on actual loop time
WEND
RETURN
MeasureHigh:
HighTime = 0
While Signal = 0 : WEND ' Wait for low
While Signal = 1 ' Measure high level
HighTime = HighTime + 1 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweal to calibrate, depends on actual loop time
WEND
RETURN

CuriousOne
- 10th October 2016, 08:03
Modified measurelow subroutine, to show the value of LowTime:



MeasureLow:
LowTime = 0
While Signal = 1 : WEND ' Wait for low level
While Signal = 0 ' Measure low level
LowTime = LowTime + 100 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweak to calibrate, depends on actual loop time
WEND
LCDOUT $FE, $C0, "T:",DEC lowtime, " "
RETURN


It returns 600.

CuriousOne
- 10th October 2016, 08:17
This is quite strange, because I'm using 16F1829, running at 16mhz. DEFINE OSC is correct, I've launched series of pulses with 1ms duration, and checked by scope - all correct.

CuriousOne
- 10th October 2016, 08:28
Modified HighTime routine too:



MeasureHigh:
HighTime = 0
While Signal = 0 : WEND ' Wait for low
While Signal = 1 ' Measure high level
HighTime = HighTime + 1 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweal to calibrate, depends on actual loop time
WEND
LCDOUT $FE,$c0, "T2:",DEC hightime, " "
RETURN


it returns 9.

Feels like MCU is operating very slow?

richard
- 10th October 2016, 09:44
what are you expecting to see ?
how many times do you think 100uS will divide into a shade less than 1mS ?

CuriousOne
- 10th October 2016, 09:55
Where it should returned something like 9000, it returns 600, is not this strange?

richard
- 10th October 2016, 10:02
I've launched series of pulses with 1ms duration, and checked by scope - all correct

the code is expecting 10 mS pulse

HenrikOlsson
- 10th October 2016, 10:04
I goofed there. Since the BitArray actually consists of two WORDs and you want the least and most significant WORD of that array the declaration should read

LSB VAR BitArray[0]
MSB VAR BitArray[1]



Where it should returned something like 9000, it returns 600, is not this strange?
What should return 9000?
You've changed the MeasureHigh routine so it only adds 1 each time thru a loop that (ideally) takes 100us to execute. A pulse lasting for 10ms will (ideally) cause that loop to execute 100 times, you end up with 100 in (instead of 10000) in HighTime.

/Henrik.

richard
- 10th October 2016, 10:26
I modified henriks code an tested it with my simulation , works fine

'************************************************* ***************
'* Name : deMODULATOR.BAS *
'* Author : richard's modified version of henriks *
'* Notice : 2016 *
'* : All Rights Reserved *
'* Date : 10/10/2016 *
'* Version : 1.0 *
'* Notes : decodes missing pulse encoded data stream A.5 *
'* : 16F1825 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG

OSCCON=$70
DEFINE OSC 32



' PIC 16F1825



TRISA = %111110 ' Make somepins Input
trisc = %111100 ;Make some pins Input
ANSELA=0
ANSELC=0
led var latc.0 ;DEBUG
led2 var latc.1 ;DEBUG
demod var porta.5 ;demod in
X VAR byte
darta VAR byte[4]
counter var word
dm_state VAR byte
lata.0=1 ;DEBUG
clear
led=0
DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 0
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0
pause 2000
Debug "Start",13 ,10
DEFINE PULSIN_MAX 9000

Code:
HighTime VAR WORD
LowTime VAR WORD



WaitForStartBit:
GOSUB MeasureLow

IF (LowTime < 9500) OR (LowTime > 11000) THEN WaitForStartBit ' 9.5-10.5ms qualifies
led2=1
GOSUB MeasureHigh
IF (HighTime < 1500) OR (HighTime > 2500) THEN WaitForStartBit ' 1.5-2.5ms qualifies
led2=0
NextLevel:
For x = 0 to 31
GOSUB MeasureLow
IF LowTime < 1000 then
darta .0[x] = 0
else
darta .0[x] = 1
endif
NEXT
led=1
Debug 13 ,10 ,bin8 darta[3],bin8 darta[2],bin8 darta[1],bin8 darta[0] ;DEBUG
Pause 1000
led=0
Goto WaitForStartBit

MeasureLow:
LowTime = 0
While demod = 1 : WEND ' Wait for low level
While demod = 0 ' Measure low level
LowTime = LowTime + 100 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweak to calibrate, depends on actual loop time
WEND
RETURN

MeasureHigh:
HighTime = 0
While demod = 0 : WEND ' Wait for low
While demod = 1 ' Measure high level
HighTime = HighTime + 100 ' Resolution is 100us, change if needed
PauseUS 92 ' Tweal to calibrate, depends on actual loop time
WEND
RETURN

richard
- 10th October 2016, 10:36
for comparison I came up with this , oddly it uses mode code space


'************************************************* ***************
'* Name : deMODULATOR.BAS *
'* Author : richard *
'* Notice : Copyright (c) 2016 *
'* : All Rights Reserved *
'* Date : 5/29/2016 *
'* Version : 1.0 *
'* Notes : decodes missing pulse encoded data stream A.5 *
'* : 16F1825 *
'************************************************* ***************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _CP_OFF & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CLKOUTEN_OFF
__config _CONFIG2, _PLLEN_ON & _LVP_OFF
#ENDCONFIG

OSCCON=$70
DEFINE OSC 32



' PIC 16F1825



TRISA = %111110 ' Make somepins Input
trisc = %111100 ;Make some pins Input
ANSELA=0
ANSELC=0
led var latc.0 ;DEBUG
led2 var latc.1 ;DEBUG
demod var porta.5 ;demod in
X VAR byte
darta VAR byte[4]
counter var word
dm_state VAR byte
lata.0=1 ;DEBUG
clear
led=0
DEFINE DEBUG_REG PORTA
DEFINE DEBUG_BIT 0
DEFINE DEBUG_BAUD 9600
DEFINE DEBUG_MODE 0
pause 2000
Debug "Start",13 ,10
DEFINE PULSIN_MAX 9000

main:
select case dm_state
case 0
PULSIN demod, 0, counter
if counter > 7800 then
dm_state=1
x=0
endif
case 1
pir1.1=0
tmr2=0
t2con=7
while demod : wend
if pir1.1 | (tmr2 < 220) then
dm_state=0
else
dm_state=2
tmr2=0
endif
case 2
while !demod : wend
t2con=0
if pir1.1 then
dm_state=0
led=1
endif
if tmr2 < 150 then
darta.0[x]=0
else
darta.0[x]=1
endif
tmr2=0
x=x+1
if x >31 then
dm_state=3
else
while demod : wend
t2con=7
endif
case 3
led2=1 ;DEBUG
' Debug 13 ,10 ,hex2 darta[3] ,hex2 darta[2],hex2 darta[1],hex2 darta[0] ;DEBUG
Debug 13 ,10 ,bin8 darta[3],bin8 darta[2],bin8 darta[1],bin8 darta[0] ;DEBUG
pause 200
led2=0 ;DEBUG
dm_state=0
end select

goto main

CuriousOne
- 10th October 2016, 10:53
the 1ms was just test, I used it to check MCU speed, whenever OSCCON and DEFINE OSC were correct, later it was removed.

I have Henrik's code running, I connect it to actual hardware, and width of large pulse, which should be 9000us, measured only 600 ?

CuriousOne
- 10th October 2016, 10:58
I've copied all code from post #35, including timings.

http://www.picbasic.co.uk/forum/showthread.php?t=21172&p=138165#post138165

richard
- 10th October 2016, 10:59
I have Henrik's code running, I connect it to actual hardware, and width of large pulse, which should be 9000us, measured only 600 ?

then you are doing something wrong ,plus you said in previous posts the pulse was 9900uS it makes a difference . whats correct ?
your looking more scatterlogical than my exwife

CuriousOne
- 10th October 2016, 11:37
haha, no, I'm not blond :)
Just I'm multi-tasking very hard.

9000, 9900, it was just typo, exact timings are given on the previous page. I don't know what I'm doing wrong, since code is Henrik's. As I said, I verified MCU speed and OSC settings, and they are all correct. Pulse timings are also correct, verified using two different scopes. this is only what I can do.