CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

12F1822 PWM problem
Goto page Previous  1, 2, 3
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Thu Mar 11, 2021 12:50 pm     Reply with quote

On a modern compiler, the pwm_off syntax would work, provided the output
'floats off'.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Sun May 23, 2021 5:03 pm     Reply with quote

I finally found some code that I could use for the 12F1822, using the NEC protocol, Ive been studying alot of assembly code, and seem to have a better grasp on it, I would like to learn more C, but at least I think Im getting a head start. I'll post the asm file. It would be nice to have a C version of this.

an include file contains all the setup info.
Code:

;**********************************************************************
; BROWN AUDIO LABS                                                    *
; PROJECT: Volume and Relay Control                                   *
; INTERNAL CLOCK: 4Mhz                                                *
; NEC FORMAT @38KHz                                                   *
; ADDRESS ID = 0xBA                                                    *
; CMD  = 0x10                                                        *
; CMD  = 0x20                                                        *
; CMD  = 0x30                                                        *
; CMD  = 0x40                                                        *
; CMD  = 0x50                                                        *
;**********************************************************************
   include "devices_setup(NEC).inc"

CLOCK_RATIO   equ CLOCK_FREQUENCY/4000000      ; 8MHz = 1/2usec per ins, 4MHz = 1usec per ins


; 8-pin DIP
;         VDD -|1   8|- VSS
;         GP5 -|2   7|- GP0
;         GP4 -|3   6|- GP1
;         GP3 -|4   5|- GP2
;


#define PIN_IR    3   ; MCLR can only be an input
#define PIN_MTR1  0
#define PIN_MTR2  1
#define PIN_RLY1  2
#define PIN_RLY2  4
#define PIN_RLY3  5

#define RLY_MASK  (1<<PIN_RLY1)|(1<<PIN_RLY2)|(1<<PIN_RLY3)

#define PINPORT_IR   PORTIO,PIN_IR
#define PINPORT_MTR1 PORTIO,PIN_MTR1
#define PINPORT_MTR2 PORTIO,PIN_MTR2
#define PINPORT_RLY1 PORTIO,PIN_RLY1
#define PINPORT_RLY2 PORTIO,PIN_RLY2   
#define PINPORT_RLY3 PORTIO,PIN_RLY3
#define TRIS_BITS (1<<PIN_IR)


ADDRS_ID       equ 0xBA
MTR1_CMD       equ 0x10
MTR2_CMD       equ 0x20
RLY1_CMD       equ 0x30
RLY2_CMD       equ 0x40
RLY3_CMD       equ 0x50


   cblock 
ADDRS
INV_ADDRS
CMD
INV_CMD
   endc

; We sample the input line in chunks, and make decisions based on the 8-bit counts of the high/low durations.
; A chunk is a number of samples, within each chunk we check for at least 75% of the samples being high or low.
; Longer chunks handle noise better, but give less resolution for the overall duration timing.
CHUNK_USEC   equ 55
CHUNK_INS   equ CHUNK_USEC*INS_PER_USEC

; Sanity check the chunk size
#if (CHUNK_INS%5)!=0
   error Chunk length must be a multiple of 5 instructions
#else
#if (CHUNK_INS<40)
   error Chunk length less than 8 samples
#else
#if (((92632/(10*CHUNK_USEC))*150/100)>=256)
   error Chunk length too short, 150% of 9.2ms is more than 256 chunks
#else
#if ((5789/(10*CHUNK_USEC))<3)
   error Chunk length too long, need at least 3 samples in the 0.5789ms pulses
#endif
#endif
#endif
#endif

; With 55usec chunks (4MHz=11 loops, 8MHz=22 loops) the timings we are interested in are:
;   Duration   Chunks   Desc
;   9.2632ms   ~168   (hi) start pulse
;   0.5789ms   10.5   (hi) data / stop high bit
;   4.6316ms   ~84   (lo) gap after start bit
;   0.5789ms   10.5   (lo) data bit '0' gap
;   1.7368ms   31.5   (lo) data bit '1' gap


; Return the number of high chunks in FUNC_TMP0, and return STATUS,C set if we get an error (more than 256 high chunks)
time_hi:
   clrf   FUNC_TMP0
time_h1:
   movlw   CHUNK_INS/5
   movwf   FUNC_TMP1
   movlw   CHUNK_INS*2/(3*5)
   movwf   FUNC_TMP2   ; Target count is 2/3 high
time_h2:
   btfss   PINPORT_IR   ; IR receiver outputs a low when we have a signal, so skip if high (so no signal)
   decf   FUNC_TMP2,F
   decfsz   FUNC_TMP1,F
   BRA   time_h2
   bcf   STATUS,C   ; Assume no error
   btfss   FUNC_TMP2,7   ; Top bit should have gone negative, if was high for 2/3 or more of the samples
   retlw   0x22      ; Now low, so return FUNC_TMP0 count
   incfsz   FUNC_TMP0,F
   BRA   time_h1
   bsf   STATUS,C   ; Is too long (55usec*256=14.1msec)
   retlw   0x33

; Return the number of low chunks in FUNC_TMP0, and return STATUS,C set if we get an error (more than 256 low chunks)
time_lo:
   clrf   FUNC_TMP0
time_l1:
   movlw   CHUNK_INS/5
   movwf   FUNC_TMP1
   movlw   CHUNK_INS*2/(3*5)
   movwf   FUNC_TMP2   ; Target count is 2/3 low
time_l2:
   btfsc   PINPORT_IR   ; IR receiver outputs a low when we have a signal, so skip if low (so have signal)
   decf   FUNC_TMP2,F
   decfsz   FUNC_TMP1,F
   BRA   time_l2
   bcf   STATUS,C   ; Assume no error
   btfss   FUNC_TMP2,7   ; Top bit should have gone negative, if was low for 2/3 or more of the samples
   retlw   0x22      ; Now high, so return FUNC_TMP0 count
   incfsz   FUNC_TMP0,F
   BRA   time_l1
   bsf   STATUS,C   ; Is too long (55usec*256=14.1msec)
   retlw   0x33

; -----------------------------------------------------------------

   STARTUP_CODE

   clrf   PORTIO
reset:            ; Power on, or no codes for 100ms+
   movlw   ~((1<<PIN_MTR1)|(1<<PIN_MTR2))
   andwf   PORTIO,F   ; Clear the up/down motor outputs


wait_reset:
   movlw   1+(100000/(256*CHUNK_USEC)) ; Wait for 100ms+ worth of chunks
   movwf   FUNC_TMP3   ; time_lo/hi uses TMP0/1/2
wait_count:
   decf   FUNC_TMP3,F
   btfsc   FUNC_TMP3,7
   BRA   reset
   clrf   ADDRS
   clrf   INV_ADDRS
   clrf   CMD
   clrf   INV_CMD
   bsf   INV_CMD,0   ; When this bit pops out the top, we're done
   call   time_lo
   btfsc   STATUS,C
   BRA   wait_count   ; timeout, so is still low!
   ; This is either a start bit (so upto 9ms on+4.5ms off) or a data bit (0.5789ms high)
   call   time_hi
   btfsc   STATUS,C
   BRA   reset      ; timeout, so is still high!
   movlw   5789*150/(CHUNK_USEC*1000)      ; 578.9 usec*150%
   subwf   FUNC_TMP0,W   ; W=Count-Target
   btfss   STATUS,C
   BRA   got_first   ; Got borrow, so <15, so was the first bit, so skip wait
   call   time_lo
   btfsc   STATUS,C
   BRA   wait_count   ; timeout, so is still low!
   movlw   46316*50/(CHUNK_USEC*1000)   ; Look for 50% of 4.6ms
   subwf   FUNC_TMP0,W   ; W=Count-Target
   btfss   STATUS,C
   BRA   wait_count   ; Got borrow, so <Target, so bad !
main_bit:
   call   time_hi
   btfsc   STATUS,C
   BRA   reset      ; timeout, so is still high!
   movlw   (5789*150/(CHUNK_USEC*1000))-1      ; 578.9 usec*150%
   subwf   FUNC_TMP0,W   ; W=Count-(Target-1)
   btfsc   STATUS,C
   BRA   reset      ; No borrow, so >=(Target-1), so too long
got_first:
   call   time_lo
   btfsc   STATUS,C
   BRA   reset      ; timeout, so is still lo!
   movlw   ((17368*150)/(CHUNK_USEC*1000))-1      ; Look for longer than 150% of 1736.8
   subwf   FUNC_TMP0,W   ; W=Count-(Target-1)
   btfsc   STATUS,C
   BRA   check_rpt   ; No borrow, so Count is really big, check if it's the repeat
   movlw   ((5789+17368)/(CHUNK_USEC*20))-1      ; Look for midpoint of 578.9usec and 1736.8usec
   subwf   FUNC_TMP0,W   ; W=Count-(Target-1)

   rlf   INV_CMD,F   ; the sub leaves the borrow/carry in C, shift into LSB
   rlf   CMD,F
   rlf   INV_ADDRS,F
   rlf   ADDRS,F
   btfss   STATUS,C
   BRA   main_bit   ; Marker bit didn't ripple out, so go again
   call   time_hi      ; Clear stop bit

   comf   INV_ADDRS,W
   xorwf   ADDRS,W
   btfss   STATUS,Z
   BRA   reset      ; Device ID bits weren't compliments
   
   comf   INV_CMD,W
   xorwf   CMD,W
   btfss   STATUS,Z
   BRA   reset      ; Code bits weren't compliments

   movlw   ADDRS_ID
   xorwf   ADDRS,W
   btfss   STATUS,Z
   BRA   reset      ; Device ID isn't the one we're looking for
;
   movlw   MTR1_CMD
   xorwf   CMD,W
   btfss   STATUS,Z
   BRA   not_mtr1
is_mtr1:
   bcf   PINPORT_MTR2
   bsf   PINPORT_MTR1
   BRA   wait_reset   ; All done
not_mtr1:

   movlw   MTR2_CMD
   xorwf   CMD,W
   btfss   STATUS,Z
   BRA   not_mtr2   ; Not motor2 code
is_mtr2:
   bcf   PINPORT_MTR1
   bsf   PINPORT_MTR2
   BRA   wait_reset   ; All done
not_mtr2:
        movfw   CMD
   xorlw   RLY1_CMD
   skpz
   BRA     not_rly1
is_rly1:   
   movlw ~(RLY_MASK)
        andwf   PORTIO,F
        movlw   1<<PIN_RLY1
        xorwf   PORTIO,F   ; Toggle pin
   BRA   wait_reset   ; All done

not_rly1:   
        movfw   CMD
   xorlw   RLY2_CMD
   skpz
   BRA     not_rly2
is_rly2:   
   movlw ~(RLY_MASK)
        andwf   PORTIO,F
        movlw   1<<PIN_RLY2
   xorwf   PORTIO,F   ; Toggle pin
   BRA   wait_reset   ; All done
not_rly2:   
   movfw   CMD
   xorlw   RLY3_CMD
   skpz
   BRA     not_rly3
is_rly3:
   movlw ~(RLY_MASK)
        andwf   PORTIO,F
        movlw   1<<PIN_RLY3
   xorwf   PORTIO,F   ; Toggle pin
   BRA   wait_reset   ; All done
   
not_rly3:   
         goto   reset

   
   

; We got a reasonable length bit, followed by a really long gap, if it's the first bit, then it's a repeat
check_rpt:
   movfw   ADDRS
   iorwf   INV_ADDRS,W
   iorwf   CMD,W
   btfss   STATUS,Z
   BRA   wait_count   ; Not first bit, we have some others, so reset
   movlw   0x01
   xorwf   CMD,W
   btfss   STATUS,Z
   BRA   wait_count   ; Not first bit
   BRA   wait_reset   ; Was the first bit, so this was a repeat, leave the outputs as they are

   end
Ttelmah



Joined: 11 Mar 2010
Posts: 19215

View user's profile Send private message

PostPosted: Mon May 24, 2021 2:13 am     Reply with quote

You do realise that this is code to _receive_ the NEC protocol, not to generate
it.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Mon May 24, 2021 4:31 am     Reply with quote

Ttelmah wrote:
You do realise that this is code to _receive_ the NEC protocol, not to generate
it.


My apologies, I should have posted under a new thread.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Mon May 24, 2021 4:34 am     Reply with quote

The transmitter code

Code:


;**********************************************************************
; BROWN AUDIO LABS                                                    *
; PROJECT: 5 button remote control                                    *
; INTERNAL CLOCK: 4Mhz                                                *
; NEC FORMAT @38KHz                                                   *
; DEVICE ID = 0xBA                                                    *
; CODE  = 0x12                                                        *
; CODE  = 0x34                                                        *
; CODE  = 0x56                                                        *
; CODE  = 0x65                                                        *
; CODE  = 0x77                                                        *
;**********************************************************************   
   include "devices_setup(NEC).inc"


; 8-pin DIP                12FXXX/16FXXXXX
;          VDD 1  8 VSS
;          GP5 2  7 GP0/ICSPDAT
;          GP4 3  6 GP1/ICSPCLK
; Vpp/MCLR/GP3 4  5 GP2
;

#define PIN_LED  2   ; pin 2
#define PIN_BUT1 0   ; pin 7
#define PIN_BUT2 1   ; pin 6
#define PIN_BUT3 3   ; pin 4
#define PIN_BUT4 4   ; pin 3
#define PIN_BUT5 5   ; pin 2
   
#define PINPORT_LED   PORTIO,PIN_LED
#define PINPORT_BUT1   PORTIO,PIN_BUT1
#define PINPORT_BUT2   PORTIO,PIN_BUT2
#define PINPORT_BUT3   PORTIO,PIN_BUT3
#define PINPORT_BUT4    PORTIO,PIN_BUT4
#define PINPORT_BUT5    PORTIO,PIN_BUT5
#define TRIS_BITS ((1<<PIN_BUT1)|(1<<PIN_BUT2)|(1<<PIN_BUT3)|(1<<PIN_BUT4)|(1<<PIN_BUT5))

DEVICE_ID   equ 0xBA
PIN1_CODE   equ 0x10
PIN2_CODE   equ 0x20
PIN3_CODE   equ 0x30
PIN4_CODE       equ 0x40
PIN5_CODE       equ 0x50

; ----------------------------------------------------------------------

   cblock
TX_BUF:4
DBBUT
   endc


; Do single 38KHz cycle, should be 26.3 usec, so 26us is 1.2% low, which is OK, but we tweak via the OSCCAL to run a bit slower
IR_ONOFF macro skip
   bcf   PINPORT_LED
   WAIT_INS (13*INS_PER_USEC)-1   ; 13us high, inc set instruction
   bsf   PINPORT_LED
   WAIT_INS ((13*INS_PER_USEC)-(1+(skip))) ; 13us low, inc clr instruction, and any extras
   endm

; Send DEVICE_ID/!DEVICE_ID/W/!W as 32-bit NEC code
send_code
   movwf   FUNC_TMP1
   movlw   352/2      ; 352 cycles of 38KHz = 9ms
   movwf   FUNC_TMP0
ir_start
   IR_ONOFF 0
   IR_ONOFF 3
   decfsz   FUNC_TMP0,F
   BRA   ir_start

   movlw   4632/24      ; 4.5ms gap (=192*24us)
   movwf   FUNC_TMP0
ir_space
   WAIT_INS (24*INS_PER_USEC)-3   ; 24 us per loop
   decfsz   FUNC_TMP0,F
   BRA   ir_space

   movlw   DEVICE_ID
   movwf   TX_BUF
   movlw   ~DEVICE_ID
   movwf   TX_BUF+1
   movfw   FUNC_TMP1
   movwf   TX_BUF+2
   comf   FUNC_TMP1,W
   movwf   TX_BUF+3
nec_ir_byte
   movlw   32
   movwf   FUNC_TMP2
nec_ir_bit
   IR_ONOFF 2
   movlw   21
   movwf   FUNC_TMP0
nec_ir_bit_on
   IR_ONOFF 3
   decfsz   FUNC_TMP0,F
   BRA   nec_ir_bit_on
   rlf   TX_BUF+3,F
   rlf   TX_BUF+2,F
   rlf   TX_BUF+1,F
   rlf   TX_BUF+0,F
   movlw   3*44-1
   btfss   STATUS,C
   movlw   44-1
   movwf   FUNC_TMP0
   WAIT_INS (13*INS_PER_USEC)-8
nec_ir_bit_off
   WAIT_INS (13*INS_PER_USEC)-3      ; 13us per loop
   decfsz   FUNC_TMP0,F
   BRA   nec_ir_bit_off
   decfsz   FUNC_TMP2,F
   BRA   nec_ir_bit
nec_ir_stop
   IR_ONOFF 2
   movlw   20
   movwf   FUNC_TMP0
nec_ir_stop_lp
   IR_ONOFF 3
   decfsz   FUNC_TMP0,F
   BRA   nec_ir_stop_lp

ir_wait
   movlw   80000/2560
   movwf   FUNC_TMP1
   clrf   FUNC_TMP0      ; 256*10us=2.56ms
ir_gap
   WAIT_INS   (10*INS_PER_USEC)-3
   decfsz   FUNC_TMP0,F
   BRA   ir_gap
   decfsz   FUNC_TMP1,F
   BRA   ir_gap
   retlw   0x33

#if 1   ; DEBUG
morse_c
   bsf   PINPORT_LED
   call   wait_7_ins   ; If off, then does 7+2=9
   btfsc   STATUS,C   ; If on does 7+12=19
   call   wait_12_ins
   bcf   PINPORT_LED
   retlw   1
#endif

; -----------------------------------------------------------------
#ifdef FEATURE_12BIT
;#define WAKEUP_LABEL main_loop   ; 10F2xx don't return after sleep, they reset with special flags in STATUS.  Branch here if detected
#endif
   STARTUP_CODE

   movlw   1<<PIN_LED
   movwf   PORTIO

main_loop:
   btfsc   PINPORT_BUT1
   BRA   not_but1
   movlw   PIN1_CODE
   call   send_code
   BRA   main_loop
   
not_but1:   
   btfsc   PINPORT_BUT2
   BRA   not_but2
   movlw   PIN2_CODE
   call   send_code
   BRA   main_loop
   
not_but2:
   
        btfsc   PINPORT_BUT3
   BRA   not_but3
   movlw   PIN3_CODE
   call   send_code
   BRA     main_loop

not_but3:
       
        btfsc   PINPORT_BUT4
   BRA   not_but4
   movlw   PIN4_CODE
   call   send_code
   BRA     main_loop

not_but4:

        btfsc   PINPORT_BUT5
   BRA   no_but5
   movlw   PIN5_CODE
   call   send_code
   BRA     main_loop
no_but5:       ; If any buttons down, skip the sleep
   movlw   TRIS_BITS
   andwf   PORTIO,W
   xorlw   TRIS_BITS
   btfss   STATUS,Z
   BRA   main_loop
   
   bcf   PINPORT_LED   ; Should be off, but make sure, otherwise it will kill the battery
   sleep         ; See Microchip document TB082, Understanding Reset Events On The PIC10F20X (10F2xx will reset, not continue)
   nop         ; Some other devices will skip the instruction after a sleep, so put a NOP here
   BRA   main_loop

   end

Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3
Page 3 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group