Searching \ for '[PIC] Strange PIC12F675 or user problem... pin cro' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/devices.htm?key=pic
Search entire site for: 'Strange PIC12F675 or user problem... pin cro'.

Exact match. Not showing close matches.
PICList Thread
'[PIC] Strange PIC12F675 or user problem... pin cro'
2008\06\29@103342 by Rolf

face picon face
part 0 44 bytes
his is a multi-part message in MIME format.
part 1 4203 bytes content-type:text/plain; charset=ISO-8859-1; format=flowed (decoded 7bit)

Hi all.

Attached is the schematic for my current project. It is a wireless
garage door monitor. It uses two magnetic switches to monitor two garage
doors, and wirelessly transmits the door state and battery state to a
receiver.

The basic concept is simple. The PIC puts all pins as input except AN0
which is used to monitor the battery health. It then sleeps for about
2.5 seconds, wakes up, checks the battery state, checks the door states,
and then activates the transmitter, and transmits a 24 bit data stream
(ID, state, checksum).

The problem is that, after a number of hours (about 5) of continuously
correct operation, it starts transmitting that the one door is 'open'.

First though, some details.

The batteries are 2xAA Lithium 1.5V
IC1 is a PIC12F675 with MCLR off (pin is used as digital input). The PIC
is the DIP version and is socketed, pulled for programming, and then
re-socketed. No need for ICSP.
U1 is a 1.25V reference - REF3312 from Texas Instruments - it has a 5uA
quiescent current.
U2 is a TXM-418-LR from Linx which has 5nA drain when /PDN is pulled low.

The momentary switch is only used to generate a new ID for the
transmitter. If the switch is closed then the unit powers up (resets),
the PIC will simply run a timer until the button is released. Whatever
the value in the (8-bit) timer is when the button is released will
become the devices new ID. The button will do nothing else while the
system operates.

The door that is indicated to be open is always the one that is sensed
through GP1 (pin 6). The door sensed through GP3 is never sensed wrong
(yet).

When the system runs correctly, I measure the following values at the
various pins (using a DMM all measurements on 2000mV range except pin 1
on 20V range, all measurements to ground):
1 3.29
2 0.000
3 0.000
4 0.000
5 0.002
6 0.010 and 3.28 with the magnetic switch closed.
7 1.249
8 0.000


When the system is 'broken', I have the following measurements:
1 3.31
2 0.000
3 0.000
4 0.000
5 0.000
6 1.250 and 1.318 with the magnetic switch 'closed'
7 1.249
8 0.000

The actual values for the 'broken' situation are suspiciously similar
between pin 6 and 7... but, it is weird that it rises to 1.318V when the
switch is closed.....

I am at a loss as to what to check, what may be broken, or where the
design may be wrong.

I have tried the circuit numerous times, and have 5 different
PIC12F675's, and at least two of them have shown this 'broken' behaviour.

The trace from R9 to GP1 (the door sense trace) runs underneath both C1
and R1 which are 1206 footprint parts. I initially suspected that there
was a solder bridge from one of these pads to the trace, but, that
appears not to be the case, and, it would be a consistent problem,
rather than the delayed/intermittent one.

About the only thing I can believe to be happening is that there is a
short of some sort between pin AN0 and GP1 causing the 1.25V reference
voltage to appear on the GP1 pin. The REF3312 is able to sink current to
maintain 1.25V, so, with the effective 2K impedance 3.3V source when the
sensor circuit is closed, and with the 1K between pin AN0 and the
REF3312, I do some math, and determine....

IF the pins have a resistance bridge between them somewhere, the 1M pull
down resistor R3 is not enough to drop the voltage at pin GP1, but, when
the door is open (the switch is closed), the 3.3V source with 2K
impedance is enough to pull the 1.25V to 1.32, or to raise it 0.7V ....
but, it makes no sense that AN0 does not change.......

Finally, before I got so stuck in to the problem, I decided that the 1M
pull-down was not 'strong' enough, so, I decided that it may be a
'capacitive' build up on pin GP1 that was causing the problem. To
'resolve' this perceived issue, I decided to set the GP1 as an output,
and output low for 50us before setting the pin back to an input for
another 200us or so before reading the pin's state through GPIO. I
figured this would be enough to drain any 'spurrious' charges on the pins.

But, it was not successful....

Anyone have any ideas?

Anyone suggest another avenue to explore?

Thanks in advance

Rolf

0.0


part 2 15372 bytes content-type:image/png; (decode)


part 3 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2008\06\29@110824 by Rolf

face picon face
part 0 44 bytes
his is a multi-part message in MIME format.
part 1 5132 bytes content-type:text/plain; charset=ISO-8859-1; format=flowed (decoded 7bit)

Two additional items of information:

To 'fix' the circuit, I disconnect the battery and wait a while before
re-connecting it.

I can unplug the magnetic switch entirely leaving the circuit open and
it is still 'broken'. Also, one test showed that when working fine, with
the switch disconnected, it still later 'broke'.

Thanks again

I can supply the source code too... actually, it is attached.

Rolf

Rolf wrote:
{Quote hidden}


part 2 27458 bytes content-type:text/plain;
(decoded 7bit)

;******************************************************************************
;   This file is a basic code template for object module code                 *
;   generation on the PIC12F675. This file contains the                       *
;   basic code building blocks to build upon.                                 *
;                                                                             *
;   Refer to the MPASM User's Guide for additional information on             *
;   features of the assembler and linker (Document DS33014).                  *
;                                                                             *
;   Refer to the respective PIC data sheet for additional                     *
;   information on the instruction set.                                       *
;                                                                             *
;******************************************************************************
;                                                                             *
;    Filename:      tx.asm                                                    *
;    Date:          22 May 2008                                               *
;    File Version:  0.9                                                       *
;                                                                             *
;    Author:        Rolf Lear                                                 *
;    Company:       tuis.net                                                  *
;                                                                             *
;                                                                             *
;******************************************************************************
;                                                                             *
;    Files required: P12F675.INC                                              *
;                    12f675.lkr                                               *
;                                                                             *
;                                                                             *
;******************************************************************************
;                                                                             *
;    Notes:                                                                   *
;                                                                             *
; This program will broadcast the A/D voltage based on a 1.25V reference      *
; as well as the state of 2 digital inputs over a data link to an RF TX       *
; it is designed to work with the Linx TXM series...                          *
;                                                                             *
;                                                                             *
;******************************************************************************

;------------------------------------------------------------------------------
; PROCESSOR DECLARATION
;------------------------------------------------------------------------------

    LIST      P=12F675              ; list directive to define processor
    #INCLUDE <P12F675.INC>          ; processor specific variable definitions
    radix     dec
    errorlevel -302
    ;errorlevel +302

;------------------------------------------------------------------------------
;***** Convenient defines
;------------------------------------------------------------------------------

   ; The button is used to set an ID for the chip.
   ; connect it to the MCLR pin (which is set as digital input).
   ; Don't press the button while programming!
   #define BUTTONIO 2
   
   ; garage A io pin.
   #define GAIO 1
   ; garage B io pin
   #define GBIO 3
   ; output pin for the LED. It is shared with the data pin of the TX
   #define LEDIO 4
   ; The data pin on the TX. The LED goes on when transmitting data too.
   #define DATAIO 4
   ; the power down pin for the TX module. Uses 5nA when powered down.
   #define PDNIO 5

   ; where in EEPROM to store the ID for the device.
   #define IDADDRESS 0x00
   
   ; which bit in the flags is used for the next data state.
   #define BCTOGGLE 0
   ; whether the bit has been set in the ISR.
   #define BCISR 1
   
   ; the set happens 18 instructions after the timer resets... and,
   ; with 2 idle instructions after setting TMR0, plus the set instruction itself
   ; we need to set the timer for: 256 - (us - 21) where 'us' is the time we want in microseconds
   #define TMRSYNC 256 - (160 - 21)
   #define TMRSHRT 256 - (120 - 21)
   #define TMRLONG 256 - (200 - 21)
   

;------------------------------------------------------------------------------
;
; CONFIGURATION WORD SETUP
;
; The 'CONFIG' directive is used to embed the configuration word within the
; .asm file. The lables following the directive are located in the respective
; .inc file.  See the data sheet for additional information on configuration
; word settings.
;
;------------------------------------------------------------------------------

   __CONFIG   _CP_ON & _CPD_OFF & _BODEN_OFF & _MCLRE_OFF & _WDT_ON & _PWRTE_ON & _INTRC_OSC_NOCLKOUT

; read the specified EEPROM address, and put the value in W.
read_eeprom macro ee_address
       bsf     STATUS,RP0
       movlw   ee_address
       movwf   EEADR
       bsf     EECON1,RD
       movf    EEDATA,w
       bcf     STATUS,RP0
   endm

; write_eeprom will write the value in W to the ee-prom address 'ee_address'
write_eeprom macro ee_address
       clrwdt
       bsf STATUS,RP0
       
       movwf EEDATA
       movlw ee_address
       movwf EEADR
       
       bcf     PIR1,EEIF   ; ensure the ee-prom interrupt is not set.
       
       ; adapted from datasheet.
       bsf EECON1,WREN     ; Enable write
       bcf INTCON,GIE      ; Disable INTs
       
       movlw 0x55          ; Unlock write
       movwf EECON2        ;
       movlw 0xAA          ;
       movwf EECON2        ;
       
       bsf EECON1,WR       ; Start the write
       
       ;back to bank 0
       bcf STATUS,RP0
       
       bsf INTCON,GIE      ; Enable INTS
       
       clrwdt              ;
       btfss PIR1,EEIF     ; Wait till write completes.
       goto $-2            ;
   endm

setio_high macro pin
       bsf     latio,pin
       movf    latio,w
       movwf   GPIO
   endm
   
setio_low macro pin
       bcf     latio,pin
       movf    latio,w
       movwf   GPIO
   endm

ad_calc macro offset,value
       movlw   offset
       subwf   adtmp,f
       btfss   STATUS,C
       retlw   value
   endm

;------------------------------------------------------------------------------
; VARIABLE DEFINITIONS
;------------------------------------------------------------------------------

; example of using Shared Uninitialized Data Section
INT_VAR     UDATA_SHR   0x20  
W_TEMP      RES     1   ; variable used for context saving
STATUS_TEMP RES     1   ; variable used for context saving
latio       res     1   ; latch for GPIO
id          res     1   ; our ID
state       res     1   ; our state - battery and door...

txc         res     1   ; the tx count.

tock        res     1   ; used for a timer.....
tick        res     1   ; used for a timer.....

bcnext      res     1   ; the value to load in to the timer next.
bcflags     res     1   ; a bitmask for the t0 state..
bcxmit      res     1   ; the byte value to transmit

adtmp       res     1   ; used for A/D calculations
bctmp       res     1   ; used for broadcast things



;------------------------------------------------------------------------------
; EEPROM INITIALIZATION
;
; The 12F675 has 128 bytes of non-volatile EEPROM, starting at address 0x2100
;
;------------------------------------------------------------------------------

DATAEE    CODE  0x2100
   DE    "  Garage V1.0"          ; Place Text string in EE-PROM
DATAWWW   CODE  0x2140
   DE    "(c) Rolf Lear. spam_OUTrolfTakeThisOuTspamtuis.net"

;------------------------------------------------------------------------------
; OSCILLATOR CALIBRATION VALUE
;------------------------------------------------------------------------------

OSC       CODE    0x03FF

; Internal RC calibration value is placed at location 0x3FF by Microchip as
; a 0xADDLW K instruction, where the K is a literal value to be loaded into
; the OSCCAL register.  

;------------------------------------------------------------------------------
; RESET VECTOR
;------------------------------------------------------------------------------

RESET_VECTOR  CODE    0x0000  ; processor reset vector
       GOTO    START         ; go to beginning of program

;------------------------------------------------------------------------------
; INTERRUPT SERVICE ROUTINE
;------------------------------------------------------------------------------

INT_VECTOR    CODE    0x0004  ; interrupt vector location
       MOVWF   W_TEMP        ; save off current W register contents
       MOVF    STATUS,w      ; move status register into W register
       MOVWF   STATUS_TEMP   ; save off contents of STATUS register

; isr code can go here or be located as a call subroutine elsewhere
       clrwdt
       
; Deal with TMR0
i_tmr0  
       btfss   INTCON,T0IE
       goto i_ad
       btfss   INTCON,T0IF
       goto i_ad
       bcf     INTCON,T0IF
               ; right, the timer 0 interrupt is set.
               ; this is used to toggle the DATA line to the radio.
               ; So, toggle it to the state in bcflags,BCTOGGLE
               ; this sequence is guaranteed to take 6 instructions
               ; regardless of whether it is to be toggled on or off.
       bcf     latio,DATAIO        ; 1
       btfss   bcflags,BCTOGGLE    ; 2 or 2/3
       goto $+2                    ; 3/4
       bsf     latio,DATAIO        ; 4
       movf    latio,w             ; 5
       movwf   GPIO                ; 6
       
       movf    bcnext,w        ; now, move the next value to the timer...
       movwf   TMR0            ; this will cost some ticks on the timer too.
       
       bsf     bcflags,BCISR   ; record the fact that we have been to the ISR...
       
i_ad
       ; in the event of a A/D interrupt, the only time we call A/D is
       ; followed by a sleep. We can ignore the situation in the ISR
       ; because the handler will be the instruction after the sleep.
       ; really, the only reason we have the A/D interrupt is to wake
       ; from sleep.....
       btfss   PIR1,ADIF
       goto    i_end
       bcf     PIR1,ADIF
       

i_end

       MOVF    STATUS_TEMP,w ; retrieve copy of STATUS register
       MOVWF   STATUS        ; restore pre-isr STATUS register contents
       SWAPF   W_TEMP,f
       SWAPF   W_TEMP,w      ; restore pre-isr W register contents
       RETFIE                ; return from interrupt

;------------------------------------------------------------------------------
; MAIN PROGRAM
;------------------------------------------------------------------------------

MAIN_PROG     CODE

START

;------------------------------------------------------------------------------
; OSCCAL RESTORE (not required if internal OSC is not used)
;------------------------------------------------------------------------------

       BSF     STATUS,RP0    ; set file register bank to 1
       CALL    0x3FF         ; retrieve factory calibration value
       MOVWF   OSCCAL        ; update register with factory cal value
       ; BCF     STATUS,RP0    ; set file register bank to 0

;------------------------------------------------------------------------------
; PLACE USER PROGRAM HERE
; First, do some initialization.
;------------------------------------------------------------------------------
       movlw   b'10001111'         ; set up the option register.
       movwf   OPTION_REG          ; pull-ups off, T0 from clock, and 1:64 prescalar on WDT (about 1152ms).
       
       movlw   b'01000000'         ; set up peripheral interupts.
       movwf   PIE1                ; so that only ADIE is enabled.
       
       movlw   b'00110001'         ; Set up AN0 as analog, other pins as digital.
       movwf   ANSEL               ; and the A/D unit to use internal dediated 500kHz RC clock...
       
       bcf     STATUS,RP0          ; set file register bank to 0
       
       clrf    latio               ; make latio and
       clrf    GPIO                ; make all outputs low.

       clrf    PIR1                ; clear all peripheral Interrupt flags...
       movlw   b'11000000'         ; set up the INTCON for enable GIE and PIE.
       movwf   INTCON
       
       movlw   b'00000001'         ; Set up the A/D unit. Start with it on, set to AN0 as input.
       movwf   ADCON0              ; The AD module takes almost nothing to have on....
                                   ; numbers are ambiguous on Datasheet, but probably less than 1uA
       
       movlw   b'00000111'         ; turn off comparator. This is a power hog if on.
       movwf   CMCON
       
; Check status of 'data' input line. It will be high if we need to randomize our ID.
       btfsc GPIO,BUTTONIO;
       call  fn_new_id

       clrwdt
       
; Right, let's read our id.... from EEPROM...
       read_eeprom IDADDRESS
       movwf   id

; OK, to the business of monitoring the garage doors.
; The WDT is enabled, and will timeout  every 1.1s or so.
; the routine is to sleep until the WDT expires, then to
; broadcast our state. then to sleep all over again.

main_loop
       ; sleep will go for a second while the WDT expires.
       nop
       sleep
       ;clrf    tock
       ;clrwdt
       ;decfsz  tock
       ;goto $-2
       nop
       nop
       call    fn_get_state
       clrf    latio
       clrf    GPIO
       
       ; set the output pins as output

       bsf     STATUS,RP0
       bcf     TRISIO,PDNIO
       bcf     TRISIO,DATAIO
       bcf     STATUS,RP0

       clrf    GPIO    ; double-check the pins are low...
       
       ; enable the TX module.
       setio_high  PDNIO
       
       ; set up the timer
       clrf    TMR0
       bcf     INTCON,T0IF
       bsf     INTCON,T0IE

       ; 0. 2ms wait (or close enough....) is 2000 cycles.
       ;   do 14 150us loops instead (2100ms).
       movlw   8
       movwf   bctmp
       movlw   TMRSYNC
       call    fn_send_bit_high        
       decfsz  bctmp,f
       goto    $-3
       
       movlw   8
       movwf   bctmp
       movlw   TMRSYNC
       call    fn_send_bit_low
       decfsz  bctmp,f
       goto    $-3

       ; broadcast twice
       clrf    txc
       call    fn_broadcast
       bsf     txc,0
       call    fn_broadcast
       
       ; set the output pins back to input (saves power).
       ; first, pull pins hard to ground.
       setio_low   DATAIO
       setio_low   PDNIO

       ; then set the IO's as input....
       bsf     STATUS,RP0
       bsf     TRISIO,PDNIO
       bsf     TRISIO,DATAIO
       bcf     STATUS,RP0

       goto    main_loop
       
; -----------------------------------------
; Function that broadcasts our ID and State
; to anyone who cares to listen
; -----------------------------------------
fn_broadcast
       ; right, the broadcast is a predefined sequence.
       ; 0. Neaten up the broadcast period to a nice round number....
       ; 1. send a series of sync bits (31).
       ; 2. send a low then high bit to help lock on.
       ; 3. send the ID
       ; 4. send the state
       ; 5. send the XOR of the ID and state for validation....
       ; 6. send a transmit ID, short for the first cycle, long for the second.
       ; 7. send a single bit to clock out the receiver.
       
       ; 0. now, set the next timer interrupt for something reasonable
       ; and neat... exactly 20ms from the start of one broadcast
       ; to the start of the next.....
       clrf    bcnext          ; set up the next interval...
       bsf     bcflags,BCTOGGLE
       clrwdt
       btfss   bcflags,BCISR   ; wait for the ISR to run.
       goto    $-2
       bcf     bcflags,BCISR   ; indicate that we have come out of the wait for ISR
       ; then a low pulse.
       clrf    bcnext          ; set up the next interval...
       bcf     bcflags,BCTOGGLE
       clrwdt
       btfss   bcflags,BCISR   ; wait for the ISR to run.
       goto    $-2
       bcf     bcflags,BCISR   ; indicate that we have come out of the wait for ISR
       movlw   33              ; this is the tweak constant to make the cycle 20ms.
       movwf   bcnext;
       btfss   bcflags,BCISR   ; wait for the ISR to run.
       goto    $-2
       bcf     bcflags,BCISR   ; indicate that we have come out of the wait for ISR

               
       ; 1. send 32 sync bits.
       ;   each bit is 50/50 duty cycle, with rate of about 7.5kBaud.
       ;   this makes each part about 150us.
       ;   the trick with this code is to use the instruction time to
       ;   keep constant bit-rate.
       movlw   32
       movwf   bctmp

       movlw   TMRSYNC
       call    fn_send_bit_high
       movlw   TMRSYNC
       call    fn_send_bit_low
       decfsz  bctmp,f
       goto    $-5
       
       ; 2. send a short bit for reference....
       ;   followed by a long bit.
       call    fn_send_data_low
       call    fn_send_data_high

       ; 3. now, send the ID
       movf    id,w
       call    fn_send_w
       
       ; 4. now, send the state
       movf    state,w
       call    fn_send_w
       
       ; 5. now send the XOR
       movf    state,w
       xorwf   id,w
       call    fn_send_w
       
       ; 6. now send an ID pulse.
       ; send a short pulse if we are the first transmission,
       ; send a long pulse if we are the second.
       btfss   txc,0
       call    fn_send_data_low
       btfsc   txc,0
       call    fn_send_data_high
       
       ; 7. now send a single pulse to clock out the receiver.
       call    fn_send_data_low
       
       
   retlw 0

; -----------------------------------------
; Function that reads W, and sends the bits
; over the air....
; -----------------------------------------
fn_send_w
       movwf   bcxmit
       movlw   8
       movwf   bctmp
       
       rlf     bcxmit,f
       btfss   STATUS,C
       goto    $+3
       call    fn_send_data_high
       goto    $+2
       call    fn_send_data_low
       
       decfsz  bctmp,f
       goto    $-7
   retlw 0
   
fn_send_data_low
       movlw   TMRSHRT
       call    fn_send_bit_high
       movlw   TMRLONG
       call    fn_send_bit_low
   retlw 0
   
fn_send_data_high
       movlw   TMRLONG
       call    fn_send_bit_high
       movlw   TMRSHRT
       call    fn_send_bit_low
   retlw 0
   
; function that schedules a high value
; to be broadcast next for the time period in W
fn_send_bit_high
       movwf   bcnext          ; set up the next interval...
       bsf     bcflags,BCTOGGLE
       clrwdt
       btfss   bcflags,BCISR   ; wait for the ISR to run.
       goto    $-2
       bcf     bcflags,BCISR   ; indicate that we have come out of the wait for ISR
   retlw 0

; function that schedules a high value
; to be broadcast next for the time period in W
fn_send_bit_low
       movwf   bcnext          ; set up the next interval...
       bcf     bcflags,BCTOGGLE
       clrwdt
       btfss   bcflags,BCISR   ; wait for the ISR to run.
       goto    $-2
       bcf     bcflags,BCISR   ; indicate that we have come out of the wait for ISR
   retlw 0

       
; ---------------------------------------
; Function that reads the Battery voltage
; and converts it in to an 0.05V offset
; from 2.20V with 32 battery levels.
; ---------------------------------------
fn_get_state
   
       bsf     ADCON0,GO
       sleep
       nop
       ; double-check...
       clrwdt
       btfsc   ADCON0,GO
       goto $-2
       
       ; for debug purposes let's make the ADRESH = 150
       ; movlw 150
       ; movwf ADRESH
       
       bcf     latio,GAIO
       bcf     latio,GBIO
       ; set the door sense pins as output
       ; we set the door pins to ground to clear any capacitive charges.
       bsf     STATUS,RP0
       bcf     TRISIO,GAIO
       bcf     TRISIO,GBIO
       bcf     STATUS,RP0
       
       ; Set the input pins as 0V to clear capacitance...
       movf    latio,W
       movwf   GPIO

       ; wait 30 or so us to ensure the pin is grounded...
       movlw   10
       movwf   tick
       decfsz  tick,f
       goto    $-1
       
       ; set the door sense pins back as input
       ; the door pins were connected to ground to clear any capacitive charges.
       ; now we set them back to input.
       ; and give it a short while to settle.
       bsf     STATUS,RP0
       bsf     TRISIO,GAIO
       bsf     TRISIO,GBIO
       bcf     STATUS,RP0

       ; Right, let's do some math....
       ; the objective is to get a scaled value of the voltage to 0.05V
       ; increments on a scale of 0-32 where 0 indicates 2.0V and 40 indicates
       ; 4.0 v. We do this with table lookups....
       ; we set up the A/D to be left justified. We expect values
       ; between 319 and 640 (correspond to 4.0 and 2.0V)
       ; with the high-byte left-formatted in ADRESH, this is about 79 and 160
       ; respectively.
       ; do some sanity checking....
       movf    ADRESH,w
       sublw   79          ; W is subtracted from 79. We expect a negative result.
       btfsc   STATUS,C    ; which would make C = 0.
       goto _fn_get_state_error
       
       ; good, now check for values more than 160...
       movf    ADRESH,w
       sublw   160         ; W is subtracted from 160. We expect a value <= 160,
       btfss   STATUS,C    ; so, the result should be >= 0
       goto _fn_get_state_error
       
       ; OK, we are in the batt-voltage ball-park.
       ; we need to subtract 256 from the 10-bit A/D value, which means subtracting
       ; 64 from the high byte....
       movlw   64
       subwf   ADRESH,w
       movwf   adtmp
       
       ; now, we need to halve the 10bit value, but, we do this by shifting the Most-
       ; significant bit of the ADRESL value in to the high byte. We are certain that the high-byte will
       ; be less than 128 because, at worst, the high byte started at 160 (640/4), and we subtracted 64
       bsf     STATUS,RP0
       rlf     ADRESL,w    ; put the high-bit in to STATUS,C
       bcf     STATUS,RP0
       rlf     adtmp,f     ; move STATUS,C in to adtmp after shifting it....
       
       ; our value in adtmp will be between 31 and 191 for voltages between 4.0 and 2.0V respectively.
       ; lets make it easier to digest... subtract the value from 191 giving a value from 0 to 160 for 2.0V to 4.0V
       movf    adtmp,w
       sublw   191
       movwf   adtmp
       
       ; now, we have an 8-bit value which is relatively scaled according to the Vbatt.
       ; we need to check our lookup table to get an idea of where the actual voltage is...
       ; the lookup function will return the voltage as a number of 0.05V offsets from 2.0V
       call fn_vbatt_lookup
   
       movwf   state
       
       btfsc   GPIO,GAIO
       bsf     state,7
       
       btfsc   GPIO, GBIO
       bsf     state,6
       
       clrwdt
       
   retlw 0;
_fn_get_state_error
       movlw   0x01
       movwf   state
       
       btfsc   GPIO,GAIO
       bsf     state,7
       
       btfsc   GPIO, GBIO
       bsf     state,6
       
   
   retlw 0

fn_vbatt_lookup
       ; this is a series of 'sieve' fall throughs.
       ; we keep subtracting a pre-calculated value from adtmp
       ; until it breaks through zero. at which point we return
       ; the 0.05V offset from 2.0V
       
       ; the ad_calc macro will subtract the first argument, and,
       ; if the result is less than zero, it will return the second argument.
       ; i.e. if adtmp starts at 5, it will subtract 8, which results
       ; in a negative value, so we will return the constant 0
       
       ; the table looks like:
       
           ; adtmp        V            ret        Off-set
           ;        0        2.00        0        
           ad_calc 8,0
           ;        8        2.05        1        8
           ad_calc 7,1
           ;        15        2.10        2        7
           ad_calc 7,2
           ;        22        2.15        3        7
           ad_calc 7,3
           ;        29        2.20        4        7
           ad_calc 6,4
           ;        35        2.25        5        6
           ad_calc 7,5
           ;        42        2.30        6        7
           ad_calc 5,6
           ;        47        2.35        7        5
           ad_calc 6,7
           ;        53        2.40        8        6
           ad_calc 6,8
           ;        59        2.45        9        6
           ad_calc 5,9
           ;        64        2.50        10        5
           ad_calc 5,10
           ;        69        2.55        11        5
           ad_calc 5,11
           ;        74        2.60        12        5
           ad_calc 4,12
           ;        78        2.65        13        4
           ad_calc 5,13
           ;        83        2.70        14        5
           ad_calc 4,14
           ;        87        2.75        15        4
           ad_calc 4,15
           ;        91        2.80        16        4
           ad_calc 4,16
           ;        95        2.85        17        4
           ad_calc 4,17
           ;        99        2.90        18        4
           ad_calc 4,18
           ;        103        2.95        19        4
           ad_calc 3,19
           ;        106        3.00        20        3
           ad_calc 4,20
           ;        110        3.05        21        4
           ad_calc 3,21
           ;        113        3.10        22        3
           ad_calc 4,22
           ;        117        3.15        23        4
           ad_calc 3,23
           ;        120        3.20        24        3
           ad_calc 3,24
           ;        123        3.25        25        3
           ad_calc 3,25
           ;        126        3.30        26        3
           ad_calc 3,26
           ;        129        3.35        27        3
           ad_calc 2,27
           ;        131        3.40        28        2
           ad_calc 3,28
           ;        134        3.45        29        3
           ad_calc 3,29
           ;        137        3.50        30        3
           ad_calc 2,30
           ;        139        3.55        31        2
           ad_calc 3,31
           ;        142        3.60        32        3
           ad_calc 2,32
           ;        144        3.65        33        2
           ad_calc 3,33
           ;        147        3.70        34        3
           ad_calc 2,34
           ;        149        3.75        35        2
           ad_calc 2,35
           ;        151        3.80        36        2
           ad_calc 2,36
           ;        153        3.85        37        2
           ad_calc 3,37
           ;        156        3.90        38        3
           ad_calc 2,38
           ;        158        3.95        39        2
           ad_calc 2,39
           ;        160        4.00        40        2
   retlw 40
   
       
; --------------------------------
; Function to create new ID for TX
; --------------------------------
fn_new_id
       ; we come here if the button is pressed when the chip resets.
       ; we start the timer, and let it run until the button is no longer pressed.
       ; then we use the value in the timer to produce a new ID, and store the ID in EEPROM.
       ; TMR0 runs continuously. We don't really care what the value is.
       
       ; make the LED output
       bsf STATUS,RP0
       bcf TRISIO,LEDIO
       bcf STATUS,RP0
       
       setio_high   LEDIO

       btfsc GPIO, BUTTONIO    ; do a tight loop to get release-point
       goto $-1    ; for when user lets go of button.
       
       ; right, the user has released the button.
       ; because the loop is 3 instructions long, it could cause funny gaps in possible numbers.
       ; but, when it wraps around it will be a different sequence.
       movfw   TMR0
       
       write_eeprom IDADDRESS
       
       ; OK, the value is written to EEPROM.
       setio_low   LEDIO
       
       ; turn the LED back to input.
       bsf STATUS,RP0
       bsf TRISIO,LEDIO
       bcf STATUS,RP0
       
   retlw 0

       END                       ; directive 'end of program'



part 3 35 bytes content-type:text/plain; charset="us-ascii"
(decoded 7bit)

2008\06\29@131646 by Rolf

face picon face
Hmmm...

I found a bug in the code. I was not ensuring I was in memory bank 0 in
the ISR. This could have caused all sorts of problems, I guess, but,
could it have caused this one? The only SFR's that the ISR modifies are
GPIO, and TMR0 which in turn, if I was in the wrong bank, would have
modified TRISIO, and the OPTION register.

I guess the combination of those two registers could do some pretty
weird things to the code, but, changes to the prescalar or TMR0 clock
source would have been very obvious, and changes to the TRISIO would
also have been noticed.... I think.

Anyway, I have fixed the code, but now have to wait (forever) to see if
it breaks again.....

Still looking for advice.

Rolf

Rolf wrote:
{Quote hidden}

[snip]

>> Anyone have any ideas?
>>
>> Anyone suggest another avenue to explore?
>>
>> Thanks in advance
>>
>> Rolf

2008\06\29@135958 by Michael Hagen

flavicon
face
Nice project Rolf!

If you have long wires going to your door sensor magnets, I would suggest
lowering the 1M to ground to 10K and bypassing them with caps.  You have
quite an "antenna system" there.  In fact I would use a dual opto-isolator
on those inputs.  I did that on quite a few projects in a factory
environment.
I know you are on batteries, but isolating those wires from rf interference
is necessary.  Besides radio RF there are other things in the garage, tools,
washer, dryer, and the garage door motors themselves.  All could cause
problems.
Maybe you could use a counter hooked to your sleep interrupt to extend data
transmission to a few minutes to save power too?

My Ham radio here caused the neighbors solar circulation system to start
when I went on 40 and 20 M!
They were really mad at me when they figured it out.
The wires were just right, about 33ft long!  Several 0.1uf caps saved the
day.

What do you have figured out for a receiver?  Is it done yet?

Now if I could just shut the doors from inside the house with this system?
Oh...another project!

Good Luck,

Mike

{Original Message removed}

2008\06\29@151155 by Rolf

face picon face
Thanks...

The device has two door channels. Building it for myself, and then
another for a friend.

The wires on the magnetic switches are about a foot long. Pretty short I
thought. The device will sit between the two doors on the centre column.

I debated the 1M pull downs. I pull all pins down except the AN0 pin. I
figured 1M was at the high end, but I did not want to go as low as 10K.
I could have gone 100K or there abouts, but I was really pushing for
long battery life. In the end, I guess I get 4 years of continuous use
out of two 3000mAh Lithium cells, and because of the nice discharge
curve, the power will be there till the end.

I could change out the 1M resistors easily, but, they seem to be
working, unless they are not, of course.

My problem is that the circuit board is home-made. I believe it to be of
high quality and I did a full board test before I soldered anything on.
There were no bridged traces, and, after soldering on everything, I had
one bridged trace which I was able to resolve...

It is possible that there is another bridged trace, but I can't find it,
and I have looked hard. Also, because I don't have a solder mask, I have
'brushed' the board with epoxy to protect the exposed copper. Changing
things now will be a little messy, but possible.

I was sort of thinking that I could enter the project in to Jason's PCB
contest to get free PCB's.... but I may just go through sparkfun too.
But, first it has to work.

As for the antenna, I am using an RP-SMA mounted antenna, and it has 4
ground 'pins'. That's why it has the 4 legs.

The receiver is already designed, built, soldered too. It all works
quite well, when it works. I have been doing this one for a few months
now, it is really frustrating to only find the problem now...

Rolf



Michael Hagen wrote:
{Quote hidden}

> {Original Message removed}

2008\06\29@163118 by Rolf

face picon face
Hi all.

Nope, problem still there. Somewhere between 2.5 and 3 hours to manifest
this time.

Anyone? ;-)

Rolf

Rolf wrote:
{Quote hidden}

2008\06\29@170316 by Richard Prosser

picon face
Rolf,

I'd also suggest stronger pulldowns than 1Meg on the door switches
(and capacitors), To minimise power consumption, maybe retain the 1Meg
resistors, but add 10ks to a "spare" pin and activate these only when
taking a reading. You should be able to figure out a way to use pin 5
as the pulldown pin as it's only used once for code setting. (I
think).

I was going to suggest swapping the connections from the "good" &
"bad" doors, but since the problem remains with neither attached, it
seems more a software or  pcb problem than external hardware.

Since it always (?) works OK for the first few hours, I'd suspect a
software, rather than hardware issue.

Getting the memory banking wrong can lead to all sorts of strange
problems and I wouldn't have been surprised if your problem is now
fixed (But obviously not however, based on your latest email).
Possibly another, similar error somewhere?

Richard P




2008/6/30 Rolf <.....learrKILLspamspam@spam@rogers.com>:
{Quote hidden}

>> {Original Message removed}

2008\06\29@174127 by Dennis Crawley

picon face
On Sunday, June 29, 2008 5:30 PM [GMT-3=CET],
Rolf  wrote:

> Hi all.
>
> Nope, problem still there. Somewhere between 2.5 and 3 hours to manifest
> this time.
>
> Anyone? ;-)
>
> Rolf

Rolf,
I know is somewhat anoying, but Do you have the same problem when you test
it over your working table?
I don't think you have noise.

Since this is the unique pin that makes you crazy, why you don't use another
pin? or switch the function pin to another?, or try with another pic?,...
just to be sure is not the damn pic.

I'll dig into the code now.
bye
Dennis




2008\06\29@201955 by Rolf

face picon face
Hi Richard, all.

I have replaced the 1M pull downs on the doors with 100K pull downs. I
also pulled up the R1 1K resistor that feeds the 1.25V to the A/D unit.
The trace for the door runs onder this 1206 resistor, so I thought there
may be a bridge under it. Well, there *may* have been. When I ripped it
up I found some un-melted solder paste there...

Well, I put another 1K resistor back there and I'm hoping this resolves it.

I followed the discussion not so long ago about solder paste, and, since
then I have not use ot for hand-soldering (I did a 'toaster-oven'
project a while back that I used the paste for, and it makes life quite
easy (or so I thought) even when hand-soldering.

Well, if the problem goes away I will attribute it to the solder paste.
If not, well, back to square one.

I'll run it overnight and see in the morning.

Attached is a small pic of the circuit (because I am quite happy with
the etching process, etc.

Hmmm, not attached, but posted here:
http://www.flickr.com/photos/gus_goose/2623093614

Rolf

Richard Prosser wrote:
{Quote hidden}

2008\06\29@212030 by Rolf

face picon face
Thanks Dennis.

Tried multiple PICs, I don't believe I had the problem when the TX unit
was in a solderless breadboard, but that could mean anything. The
circuit is now 'established' in a hand-made PCB, so I am somewhat
reluctant to cut traces and rewire it. I also 'potted' the board with
epoxy to stop the copper from oxidising. Access is a little problmatic.

Still, I have changed the 1M pull downs to 100K, and found a potential
bridge under a 1206 resistor.

The only change in the code since I posted it was to add 'bcf
STATUS,RP0' to the ISR after saving away the STATUS register. (updated,
I also bcf INTCON,T0IE after the second fn_broadcast).

Further analysis of mine indicates that the PIC is not likely to be in
the ISR with RP0 set (high memory bank). The interrupts will never be
enabled at any point when the main loop is in the high bank. Hmm,
actually, they may be... which is a bug too. Fixed now, although the
timing of the TMR0 is such that I don't believe that the ISR is entered
at when in Bank 1. I offer as evidence, that, if that were to happen,
the check for the PIR1,ADIF flag would actually hit the PIE1 register,
and swithc off the A/D Interrupt enable, causing the A/D sleep operation
to never exit till the WDT reset a full 2.3 seconds later...

This would be very obvious to me since the receiver would complain lots
and lots about a missed transmission. Further, the A/D setting would
never be reset to on, so, there would always be 5 seconds between
transmisions instead of 2.5. No, that's wrong. If the ADIE were set to
0, the A/D sleep instruction would reset the PIC and the ADIE will be
reset in the initialization routine to 1. Which will mean just one
glitch which I may miss...

All very confusing for a simple project.

Well, it is bed time for me. Let's see what has happened in the morning.

Thanks again


P.S. hope you don't waste time on this. I am thinking that the most
logical answer to my riddle was the solder paste under R1. But, it is
very weird how it manifest with a 'delayed' activation. There were times
in the past few days where I have felt that physically manipulating the
board has 'fixed' the problem, but I always deemed that to be a result
of my fingers changing the capacitive load somewhere.... but, it may
have been me 'jiggling' the bridge under R1.

Anyway, the code is relatively presentable, and I have been racking my
brain for a few days, so I would greatly appreciate another pair of eyes
to see anything else I may have missed.

Regradless, until it manifests again I am calling it 'case closed'.

Rolf


Dennis Crawley wrote:
{Quote hidden}

2008\06\30@072103 by Alan B. Pearce

face picon face
>The only change in the code since I posted it was to add 'bcf
>STATUS,RP0' to the ISR after saving away the STATUS register.
>(updated, I also bcf INTCON,T0IE after the second fn_broadcast).

I assume you are also restoring the STATUS register at the end of the
interrupt (haven't looked at the code you attached earlier) ???

2008\06\30@072945 by Rolf

face picon face
Hi all.

Everything still works this morning... holding thumbs.

Rolf

Rolf wrote:
> Thanks Dennis.
>
>
>  
[snip]
{Quote hidden}

2008\06\30@074655 by Rolf

face picon face
Alan B. Pearce wrote:
>> The only change in the code since I posted it was to add 'bcf
>> STATUS,RP0' to the ISR after saving away the STATUS register.
>> (updated, I also bcf INTCON,T0IE after the second fn_broadcast).
>>    
>
> I assume you are also restoring the STATUS register at the end of the
> interrupt (haven't looked at the code you attached earlier) ???
>
>  
Thanks Alan.

The code is base don the 'default' Microchip .asm template for the
PIC12F675. It does a full save and restore of the W and STATUS
registers. So, yes, I restore STATUS.

The receiver part of the project also uses the PIC12F675 and the same
code template. I *did* remember to switch to bank 0 in the receiver code
though.

In reference to my project in particular though, I don't believe it is
possible for the interrupt to be called when the main loop is in bank 1.
The symptoms of such an event would be very obvious if it were to
happen. Even I would have found that first time... ;-)

Thanks

Rolf

2008\06\30@123348 by olin piclist

face picon face
> The only change in the code since I posted it was to add 'bcf
> STATUS,RP0' to the ISR after saving away the STATUS register.

And why would you do that?  What about RP1?  Doing a CLRF STATUS takes care
of all three bank bits in one instruction.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\06\30@131839 by Rolf

face picon face
Olin Lathrop wrote:
>> The only change in the code since I posted it was to add 'bcf
>> STATUS,RP0' to the ISR after saving away the STATUS register.
>>    
>
> And why would you do that?  What about RP1?  Doing a CLRF STATUS takes care
> of all three bank bits in one instruction.
>
>
> ********************************************************************
> Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
> (978) 742-9014.  Gold level PIC consultants since 2000.
>  
Well, there are only two banks on the PIC12F675, and thus only RP0 (RP1
is reserved and should always be maintained as 0).

So, since all the banking I have in my program is done with bcf and bsf
STATUS,RP0 it seemed to be consistent to do it the same way in the ISR.
I have it 'mentally embedded' in my head that bcf STATUS,RP0 and bsf
STATUS,RP0 are to do with banking, and I never otherwise manipulate the
STATUS register with non-bitwise operations.

In other words, to keep things straight in my head I try to only change
what I intend to change. Changing things 'for the sake of it' leads me
in to deep dark places of despair. Also, the bcf/bsf is what the
assembler would do with a banksel instruction...

I may not be doing the best thing in your eyes on this one, but, it
keeps things somewhat straighter in my head that all banking is done the
same way.

Rolf



2008\06\30@150011 by olin piclist

face picon face
Rolf wrote:
> Well, there are only two banks on the PIC12F675, and thus only RP0
> (RP1 is reserved and should always be maintained as 0).

On the 12F675, but not so on many other PICs.  You're going to have trouble
when you copy and paste this code for use with another PIC.  It's the same
number of instructions to do it right.

> So, since all the banking I have in my program is done with bcf and
> bsf STATUS,RP0

That's another problem.  You're screwed if you ever try to copy the code for
use on a 4 bank PIC.  At the very least use BANKSEL.  Once you are
comfortable with the PIC banking, you can use my DBANKIF and related macros
that track the bank setting at assembly time.

> I have it 'mentally embedded' in my head that bcf STATUS,RP0 and bsf
> STATUS,RP0 are to do with banking, and I never otherwise manipulate
> the STATUS register with non-bitwise operations.

Then you should un-embed it.  That is a bad way to handle banking.

> In other words, to keep things straight in my head I try to only
> change what I intend to change.

But this changes between PICs, and also invites you to make a mistake by
selecting the wrong bank for a particular register.  BANKSEL is much better
in that it sets the bank to whatever is required to access the address you
specify.  On a PIC with only two banks it will only generate a single BSF or
BCF instruction on RP0.  BANKSEL eliminates the error of chosing the wrong
bank, hides the PIC-specific mechanics of switching the bank, and works
accross PICs.  There is less to keep straight in your head.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\06\30@182301 by Rolf

face picon face
Hi Olin.

I inderstand banksel, and what it does... and I know the assembler will
reduce it to a single instruction for the PIC12F675... but...

the code was written with bank 0 being the default. The thinking is that
the device is always in bank 0 except when accessing bank1 registers.
Thus, the code is simplified to a large extent, with a small scattering
of bsf and bcf STATUS,RP0.

Using this 'philosophy, I would have to do a banksel before *and after*
accessing a Bank 1 register. So, what do you choose as a banksel
'target' after accessing a bank 1 variable...

banksel TRISIO
bcf   TRISIO,0
banksel ??????

Well, I could choose something I know in the PIC12F675 is in bank 1,
like GPIO, but, banksel is supposed to be called *before* accessing a
register, not after it, and it should be called for the register being
accessed, etc. Having banksel ??? after accessing a bank 1 address is
more problematic than a specific bcf STATUS,RP0.

Anyway, there are other reasons too, just like your copy paste example.
If I ued banksels and then used the code in another device with more
banks (and RP1), then the timing of some loops would be different, etc.

Bottom line is that if I ever were to copy/paste the code it would have
a different set of issues depending on whether I used banksel of not.

As for using your development environment, well, no. I am very happy
using MPLab to do all the code, and in-place debugging. I have no
intention of introducing additional non-compatible steps to the build
environment. I have in the past downloaded and evaluated your system,
and I can see that it has many strengths. On the other hand, My
assembler programs are few, simple, and easy to manage with out the
administrative costs of your system, as well as losing the integration
with MPLab and the ICD2 and PicKit2 I already have. Also, for the larger
devices I have been using C18 with The student edition compiler, I still
keep all the debug features, as well as the integration, etc, but would
be completely incompatible with your toolset.

'Doing it right' is not necessarily clrf STATUS though, is it. It will
work fine in the ISR, but, not elsewhere. Regarless, it is an opinion
statement, and there are different times when different methods are
better. I am happy with the bcf in my context because it makes the
entire program internally consistent.

A consitent program is far more intelligible than an inconsistent one.
The strategy I have chosen is incompatible with your way of thinking,
but, from my perspective, that's OK. It makes sense to me. There may
come a time when I am ready to onvest more in the infrastructure
surrounding the code, but now is not the time. If I use copy/paste for
this code more than twice in my life I will be more than surprised.
Further, I would much rather have 'obvious' incompatibilities like
mising RP1 on a status register, than to have 'obscure' problems like
changes to program timings, and changes to relative GOTO statements that
happen when using banksel.

Rolf



Olin Lathrop wrote:
{Quote hidden}

2008\06\30@182902 by Tamas Rudnai

face picon face
Hi Rolf,

I believe that the context saving is not right in your code. You likely to
overwrite Z flag, however, I can't see any section of your code that would
use the zero flag so it might not be the case.

Tamas



;------------------------------------------------------------------------------
> ; INTERRUPT SERVICE ROUTINE
>
> ;------------------------------------------------------------------------------
>
> INT_VECTOR    CODE    0x0004  ; interrupt vector location
>        MOVWF   W_TEMP        ; save off current W register contents
>        MOVF    STATUS,w      ; move status register into W register
>        MOVWF   STATUS_TEMP   ; save off contents of STATUS register
>
>
Should be:

INT_VECTOR    CODE    0x0004  ; interrupt vector location
      MOVWF   W_TEMP        ; save off current W register contents
      SWAPF    STATUS,w      ; move status register into W register
      MOVWF   STATUS_TEMP   ; save off contents of STATUS register


i_end
>
>        MOVF    STATUS_TEMP,w ; retrieve copy of STATUS register
>        MOVWF   STATUS        ; restore pre-isr STATUS register contents
>        SWAPF   W_TEMP,f
>        SWAPF   W_TEMP,w      ; restore pre-isr W register contents
>        RETFIE                ; return from interrupt
>

Should be:

i_end

      SWAPF    STATUS_TEMP,w ; retrieve copy of STATUS register
      MOVWF   STATUS        ; restore pre-isr STATUS register contents
      SWAPF   W_TEMP,f
      SWAPF   W_TEMP,w      ; restore pre-isr W register contents
      RETFIE                ; return from interrupt

Tamas


--
Rudonix DoubleSaver
http://www.rudonix.com

2008\06\30@190657 by Rolf

face picon face
That's fascinating observation...

The code itself is unmodified from the 'template' as supplied by
Microchip, so I would be surprised... but, two observations....
1. If the MOVF,w changes Z before actually moving the value, then you
may be right, otherwise I think it is 'bulletproof'.
2. in your alternative suggestion, you have an issue with the 'restore'
section. you use swapf to get STATUS in to W, so the nybbles will be
swapped, so you only need one swapf to restore them in the return.

So, when exactly does the STATUS value get moved from the register to W?
According to mid-range-manual.... well, it appears that the register
(status) is read before the values are processed (thus re-affecting status).

Hmm. It all looks OK to me, though, using swapf may save an instruction
in the ISR....

Rolf



Tamas Rudnai wrote:
{Quote hidden}

2008\06\30@193946 by olin piclist

face picon face
Rolf wrote:
> Using this 'philosophy, I would have to do a banksel before *and after*
> accessing a Bank 1 register. So, what do you choose as a banksel
> 'target' after accessing a bank 1 variable...

I wouldn't.  I don't think that philosophy makes sense.  I would set the
bank on demand as needed.

But, if you really want to abuse BANKSEL to set access to a particular bank,
you can use the first address in the bank.  That would be the bank number
times 128.

> Also, for the larger
> devices I have been using C18 with The student edition compiler, I still
> keep all the debug features, as well as the integration, etc, but would
> be completely incompatible with your toolset.

I don't care if you use my PIC development environment or not, since it's
available for free.  However, it does work with C18.  C18 uses really stupid
stack management, but I've got a assembly time switch that causes my stuff
to use the same brain dead stack management for compatibility.  I have done
several mixed MPASM/C18 projects.

> 'Doing it right' is not necessarily clrf STATUS though, is it. It will
> work fine in the ISR, but, not elsewhere.

Right, but that's where this came up.  It's one instruction that sets the
banks to a predictable state on entry to interrupt, and it works on a 4 bank
machine too.

> Further, I would much rather have 'obvious' incompatibilities like
> mising RP1 on a status register, than to have 'obscure' problems like
> changes to program timings, and changes to relative GOTO statements that
> happen when using banksel.

Huh?  On your machine BANKSEL will always emit the exact same instruction as
you are hard coding.  The difference is that it won't screw up and select
the wrong bank.

If you're talking about moving the code to a 4 bank PIC, then BANKSEL will
take one extra instruction, but at least the bank will be correctly
selected.  Worrying about single instruction timing when the bank is wrong
is silly.  Unless you are doing something very unusual, you wouldn't be
setting the bank in the middle of some code where single instruction timing
matters.  With that kind of code, you would usually arrange to not need to
switch banks in the first place.  If your timing is really that tight, you
should probably use assembly time math to make sure the timing is met and
generate a error if it's not.  Of if you know you have extra cycles,
something like my WAITNS macro is much better than hand-counting NOPs.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\06\30@194801 by Rolf

face picon face
Hmmm... I see yu got your routine from the datasheet.

I guess this is a place where the datasheet and the example code differ.
Also, disregard my second 'observation' with your example code, I mixed
up the W and STATUS restore.

I am looking in to the code more carefully now too. I think the existing
code works fine, but, I will use the swapf anyway because it comes from
the datasheet which I trust more than the .asm template.

I am also going to run it through the MPSIM to see if it is ever a factor...

Rolf

Rolf wrote:
{Quote hidden}

2008\06\30@200014 by Rolf

face picon face
Just as a 'by the way', the Microchip datasheet and .asm templates  
suggest different ways of doing things, but, the following is from the
PIC12F675 datasheet:



MOVWF W_TEMP ;copy W to temp register,
could be in either bank
SWAPF STATUS,W ;swap status to be saved into W
BCF STATUS,RP0 ;change to bank 0 regardless of
current bank
MOVWF STATUS_TEMP ;save status to bank 0 register
:
:(ISR)
:
SWAPF STATUS_TEMP,W;swap STATUS_TEMP register into
W, sets bank to original state
MOVWF STATUS ;move W into STATUS register
SWAPF W_TEMP,F ;swap W_TEMP
SWAPF W_TEMP,W ;swap W_TEMP into W



It is very happy to use the bcf STATUS,RP0. I am not the only person who
uses bcf STATUS,RP0 and the datasheet is fairly authoritative, not? Oh,
and it does not change RP1 either! Nor does it banksel.

In my mind it makes fine sense, it has clear (or at least clearer)
meaning of what the intent of the instruction is. the clrf STATUS could
have all sorts of intended, and unintended consequences, especially
since it never works (clrf STATUS will always set STATUS,Z).

Assembler appears to be somewhat like perl, TIMTOWTDI ... ;-)

Anyway, using hybrid/your logic, it would be better not to have a 'clrf
STATUS', but to have banksel's before each SFR. Just in case you
copy/paste the code.

Regardless, this all comes down to how the program is arranged in your
mind. This is my program and it makes sense to me. I would rather use
less efficient mechanisms that work for me and are clear in my head and
that I understand, than use 'better' mechanisms that don't. At least I
know who to blame when they don't work.

Rolf

Olin Lathrop wrote:
{Quote hidden}

2008\06\30@200703 by Rolf

face picon face
MPSIM suggests the code works when entering with either STATUS,Z set as
1 or 0. The STATUS is correctly restored.

I'm still going to change it to match the datasheet.

Rolf

Rolf wrote:
{Quote hidden}

2008\06\30@201613 by Rolf

face picon face
Hi all.

Just to give some feedback... it ran fine overnight and through the day.
It all seems to be in order, but I'll give it some more time still.

Thanks

Rolf


Rolf wrote:
{Quote hidden}

2008\06\30@204632 by Tamas Rudnai

face picon face
If you look at the MOVF instruction, that changes the Z, while SWAPF does
not. Also SWAPF takes the same instruction cycle and code space, so there is
no reason not to use here. Anyway, if STATUS is entirely 0x00 then the Z
should be set after the MOVF, otherwise you will not be able to observe
difference in between using the two instructions.

Tamas




On Tue, Jul 1, 2008 at 1:06 AM, Rolf <EraseMElearrspam_OUTspamTakeThisOuTrogers.com> wrote:

{Quote hidden}

> -


'[PIC] Strange PIC12F675 or user problem... pin cro'
2008\07\01@044448 by Alan B. Pearce
face picon face
>I am looking in to the code more carefully now too. I think the existing
>code works fine, but, I will use the swapf anyway because it comes from
>the datasheet which I trust more than the .asm template.

You need to look at why SWAPF is used - big clue, look at what happens to
the flags when doing the restore at the end of the interrupt routine with
your code.

2008\07\01@075924 by olin piclist

face picon face
Rolf wrote:
> I am not the only person who
> uses bcf STATUS,RP0

Lots of people don't comment their code, but that doesn't make it a good
idea either.

> and the datasheet is fairly authoritative, not?

Not when it comes to code.  Microchip examples generally suck, and sometimes
contain outright errors.  Look at the instruction set, how the machine and
the peripherals work, then write your own code.

> the clrf STATUS could
> have all sorts of intended, and unintended consequences, especially
> since it never works (clrf STATUS will always set STATUS,Z).

Then you might as well wave a dead fish over your programs in case that
makes them work better too.

> Assembler appears to be somewhat like perl, TIMTOWTDI ... ;-)

Huh?

> Anyway, using hybrid/your logic, it would be better not to have a
> 'clrf STATUS', but to have banksel's before each SFR. Just in case you
> copy/paste the code.

Newbies should use BANKSEL in front of every reference that could be in a
different bank from the previous.  Once they get more comfortable with the
rest of the PIC, then they can go back and learn better ways to manage
banking.  Explictly writing BSF/BCF on RP0/RP1 is bad programming and is
never encouraged.

If you look at my interrupt template module, QQQ_INTR.ASPIC, you will see I
don't use BANKSEL, but my DBANKIF and DBANKIS macros.  I force the interrupt
temporary save registers to be in bank 0, and use CLRF STATUS as a single
instruction to select bank 0 regardless of what state STATUS was in or which
14 bit core PIC this is running on.  This is immediately followed by DBANKIS
0 and IBANKIS 0 to tell the assembler what the bank settings are.  After
that, the bank setting is tracked at assembly time and only the minimum bank
switching instructions are inserted by DBANKIF as needed.  This is of course
all explained in the comments too.

> I would rather use
> less efficient mechanisms that work for me and are clear in my head
> and
> that I understand, than use 'better' mechanisms that don't.

That's your business.  The discussion was only because you asked for help
here, and apparently did have some problems in this area.  Given that, you
might want to revist your thinking.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\07\01@081354 by Rolf

face picon face
Alan B. Pearce wrote:
>> I am looking in to the code more carefully now too. I think the existing
>> code works fine, but, I will use the swapf anyway because it comes from
>> the datasheet which I trust more than the .asm template.
>>    
>
> You need to look at why SWAPF is used - big clue, look at what happens to
> the flags when doing the restore at the end of the interrupt routine with
> your code.
>
>  
Hi Alan.

I am not sure what you are suggesting... oh, I see. You think that the
restore of the STATUS register is broken.... well, I don't believe it
is. I have inspected the code, inspected the datasheets, and run various
scenarios through MPSIM, and I can't see where the code is broken. If it
is in fact broken, I need you to do more than just give me a 'clue'.
Where is it.....

Here is the snippet from the file C:\Program Files\Microchip\MPASM
Suite\Template\Code\12F675TEMP.ASM. I have taken the liberty of
numbering the lines, and adding some comments of my own...:


       ORG     0x004             ; interrupt vector location       1 -
fine, get us to the reset vector.
       movwf   w_temp            ; save off current W register
contents   2 - movwf does not affect STATUS. Good.
       movf    STATUS,w          ; move status register into W register
3 - movf *does* affect STATUS,Z, but, the copy of STATUS in W is from
before the Z is (potentially) changed.
       movwf    status_temp       ; save off contents of STATUS
register  4 - movwf does not affect STATUS, Good.


; isr code can go here or be located as a call subroutine elsewhere


       movf    status_temp,w     ; retrieve copy of STATUS register  5
- movf *does* affect status, but, that's OK because we are putting the
original STATUS in to W.
       movwf    STATUS            ; restore pre-isr STATUS register
contents  6 - movwf does not affect STATUS, which is good, because we
are overwriting it's contents with W.
       swapf   w_temp,f            ; 7 - swap the W nybbles because we
want to use SWAPF again later because SWAPF does not affect STATUS.
       swapf   w_temp,w          ; restore pre-isr W register contents  
8 - the final SWAPF to W with the correct W register restore.
       retfie                    ; return from interrupt


So, the way I see it is that the template code *does the right thing*.
It may not do it the same way as the datasheet, but, it works just fine.
The lines of potential confusion are lines 2, 3, 5, and 6. Which line
has it wrong?

Also, just by the way, if I randomly select PIC 10, 12 and 16 files from
C:\Program Files\Microchip\MPASM Suite\Template\Code\ I find that either
they do not have code for the ISR, or they use the system I pasted
above. The templates for common PICS like the 12F675, 16F84A 16F628
16F648 16F877 16F88 16F887 and more *all* have the system above. Are
*all* the templates wrong for the non PIC18F parts?

Rolf

2008\07\01@082951 by Tamas Rudnai

face picon face
Hi Rolf,

> am not sure what you are suggesting... oh, I see. You think that the
> restore of the STATUS register is broken.... well, I don't believe it is.

It is actually, that context saving does not care about the Z flag...

> I have inspected the code, inspected the datasheets, and run various
> scenarios through MPSIM, and I can't see where the code is broken. If it
> is in fact broken, I need you to do more than just give me a 'clue'.
> Where is it.....

I have already mentioned, even with the code example...

Tamas


On Tue, Jul 1, 2008 at 1:13 PM, Rolf <learrspamspam_OUTrogers.com> wrote:

{Quote hidden}

> -

2008\07\01@084310 by Jinx

face picon face
> > and the datasheet is fairly authoritative, not?
>
> Not when it comes to code

Do not trust datasheet code examples. Some are too simple (bank
selection for example), others are just wrong and/or inappropriate
Copy/Pastes from other PIC datasheets

> > Assembler appears to be somewhat like perl, TIMTOWTDI ... ;-)

You can use that (whatever it means), but not BANKSEL ? !! 8-)

> > I would rather use less efficient mechanisms that work for me
> > and are clear in my head and that I understand, than use 'better'
> > mechanisms that don't

To be honest, scatterings of

BCx STATUS,RP0, with or without BCx STATUS,RP1

through code looks really untidy and is distracting and tiring to read.
Plus it's more typing and a lot easier to make a mistake with. There
are so many code faults that can be traced back to banking

2008\07\01@085010 by Alan B. Pearce

face picon face
>I am not sure what you are suggesting... oh, I see. You think
>that the restore of the STATUS register is broken....

No, I thought you were not using SWAPF at all in the restore section, but I
just went back and looked at the code that Tamas quoted, and found you were.
It is more the reason why SWAPF is used rather than a MOV instruction, that
I was trying to reinforce in your mind.

2008\07\01@085743 by Rolf

face picon face
I'm sorry for being so apparently dense, but, I disagree with you, at
least until I can see where the problem is. You have insisted that the
microchip code is wrong somewhere, saying it is with the MOVF
instruction. I have literally spent hours trying to understand the
problem, run the code, simulated it, and it all works just fine as far
as everything I have available is concerned. What more do you expect me
to do.... have you considered for a moment that you may be wrong?

In your other mail you suggested that the STATUS,Z will be
saved/restored incorrectly. There are 8 lines of code, with 2 MOVF
instructions... I believe they both work fine. You suggest that one of
them does the wrong thing. So, please, spare me some anxiety and tell me
which is broken. I have spent too much time already on this, especially
when I appear to be missing something 'obvious'.

To repeat, here are the instructions.....

      ORG     0x004
      movwf   w_temp
      movf    STATUS,w
      movwf    status_temp
; isr code can go here or be located as a call subroutine elsewhere
      movf    status_temp,w
      movwf    STATUS
      swapf   w_temp,f
      swapf   w_temp,w
      retfi


The first MOVF instruction correctly stores the current STATUS in W
(even though after the instruction the STATUS,Z may have changed).
The second MOVF may affect STATUS too, but, it is inconsequential
because STATUS is neither the source nor target of the instruction...
and the next instruction (MOVWF) will overwrite the status anyway.

So, please, the context saving *does* care about the Z bit.... if not, I
have spent a lot of time on it (based on your assertion that it is
broken), I still don't see the problem, so please spell it out for me
with a little patience...

Thanks

Rolf



Tamas Rudnai wrote:
{Quote hidden}

>> --

2008\07\01@091134 by Rolf

face picon face
Alan B. Pearce wrote:
>> I am not sure what you are suggesting... oh, I see. You think
>> that the restore of the STATUS register is broken....
>>    
>
> No, I thought you were not using SWAPF at all in the restore section, but I
> just went back and looked at the code that Tamas quoted, and found you were.
> It is more the reason why SWAPF is used rather than a MOV instruction, that
> I was trying to reinforce in your mind.
>
>  
Thanks Alan.

Yes, I know why SWAPF is used. I prefer the example routine in the
datasheet to the one in the .asm template, and I have changed my code
accordingly. SwapF does make things more transparent. I would just like
to confirm though that the original (microchip .asm template) routine is
functionally accurate. I have spent hours now trying to find holes in
it, and I can't. It is important for me to understand, and if my
understanding is wrong, then I need to know why...

Right now there is a lot of debate in this thread, and I am not sure
what has been resolved or not ;-)

Thanks

Rolf

2008\07\01@100005 by Rolf

face picon face
Hi Olin

Olin Lathrop wrote:
> Rolf wrote:
>  
>> I am not the only person who
>> uses bcf STATUS,RP0
>>    
>
> Lots of people don't comment their code, but that doesn't make it a good
> idea either.
>
>  
Agreed. You will find my code is commented.... indented consistently, etc.

>> and the datasheet is fairly authoritative, not?
>>    
>
> Not when it comes to code.  Microchip examples generally suck, and sometimes
> contain outright errors.  Look at the instruction set, how the machine and
> the peripherals work, then write your own code.
>
>  
Apparently, as a newbie, I should know when RTFDS is the right thing to
do, and when I should use my own initiative.
For what it's worth, the way I select banks is based on looking at the
instruction set, how the machine works, and then writing my own code...
but apparently this is not OK in that instance....?

There is a fine line in what you believe to be 'right' somewhere I have
not come to grips with yet....
>> the clrf STATUS could
>> have all sorts of intended, and unintended consequences, especially
>> since it never works (clrf STATUS will always set STATUS,Z).
>>    
>
> Then you might as well wave a dead fish over your programs in case that
> makes them work better too.
>
>  
If it helps, I will. Hang on, dead insects have been known to change the
bahaviour of programs, so there may be some merit.
>> Assembler appears to be somewhat like perl, TIMTOWTDI ... ;-)
>>    
>
> Huh?
>
>  
There Is More Than One Way To Do It - this is the perl 'mantra'. a
simple google of TIMTOWTDI reveals all... but, I don't expect everyone
to know that. It was intended for the audience who have already used
perl, and for those who were willing to invest some small amounts of
time to understand... Still, you expect me to research a bunch of things
in your 'domain' every time you make a reply, it would have been nice if
you could have returned the favour a little. But, as I say, it was just
meant to point out that there are many ways to skin a cat, and, the way
I have implemented are jsut different to yours, but accomplish the same
result (in the end).
{Quote hidden}

Two things... First, I am confused. I though newbies (like me) should
download your development environment and use things like QQQ_BANKIS, or
IBANKIS or something. That was the 'magic cure to all things PIC
related, it slices, dices, and does everything you need...'.

Secondly, Explicitly writing BSF/BCF on RP0/RP1 *IS* encouraged. It may
not be encouraged by YOU, and you may think it is bad programming...
but, that does not make it a universal truth. In fact, the datasheet
(which you disagree with) explicitly recommends it in the ISR.

{Quote hidden}

Olin, your PIC environment is a fantastic accomplishment, I am sure.
But, it has limitiations that I am not willing to compromise. I have
previously evaluated it, and found that the things I value in MPLab are
too important to sacrifice for your assembler pre-processor. When your
system allows the building, debugging, watching of variables, a
graphical interface, and preferablly run native on Linux (which MPLAB
does not do, but I am willing to compromise on that), then I will
re-avaluate it. The fact is that your system works fine for you, and
some others who are willing to compromise in different ways than I am.
But, it is not for everyone.

>> I would rather use
>> less efficient mechanisms that work for me and are clear in my head
>> and
>> that I understand, than use 'better' mechanisms that don't.
>>    
>
> That's your business.  The discussion was only because you asked for help
> here, and apparently did have some problems in this area.  Given that, you
> might want to revist your thinking.
>  
I absolutely agree. I did have some problems here. Some are still  
unresolved. I must always revisit my thinking. But, my problem was that
I did not ensure my memory bank in the ISR. This could have been fixed
in four 'broad' ways, with a banksel, with a bcf STATUS,RP0, with a clrf
STATUS, or with a re-implementation using your PIC macros and systems.

In each of the solutions I have to do something specific to set the
bank. Well, I could have made the same mistake using any of those
systems. If I had left out a banksel it would be the same as missing out
a clrf, or a bcf, or whatever. I did not make the mistake because I used
a bcf STATUS,RP0, I made the mistake because I am a newbie and did
*nothing*. I have learned to avoid this mistake now (though I am sure it
will happen somewhere else again). The solution to the problem is to do
*something*.

You have now suggested three different solutions to one problem. First
you said I should do a clrf STATUS. Then you said I should always use
banksels. Finally, you are suggesting I use your macros. Frankly, I
disagree with all your suggestions, and I want the program to be
consistent with the bcf STATUS,RP0, and that's fine.

Your advice is somewhat contradictory at times. Especially when you are
so emphatic with your advice for different approaches... first, you say...

> And why would you do that?  What about RP1?  Doing a CLRF STATUS takes care of all three bank bits in one instruction.


Then you say:

> That's another problem.  You're screwed if you ever try to copy the code for use on a 4 bank PIC.  At the very least use BANKSEL.  Once you are comfortable with the PIC banking, you can use my DBANKIF and related macros that track the bank setting at assembly time.


So, regardless of your own programming 'philosophy', it seems that
whatever I do would be wrong in some way according to you. I am OK with
that. I don't mind being different to you. At the same time, you are
also correct that I did come here asking for help, I did have problems
in banking. I have revisited my thinking, compared it to what you
suggest, and decided that my banking is now resolved, the solutions you
propose all have merits in their own way, but I have chosen a different
solution that makes sense to me in other ways. Debating whether to use
banksels, or whatever is not going to be much fun or use... so, I'll
move on and agree to differ with you on the 'right philosophy' for
banking. Also agree to differ with you about using your PIC environment.
Finally, also agree to differ with you on whether to consider you more
authoritative than the datasheets (I know the datasheets may be wrong,
but, so may you).

Rolf

2008\07\01@100012 by olin piclist

face picon face
Rolf wrote:
>        ORG     0x004

Don't do that.  I understand recent versions of MPASM now allow ORG in
relocatable mode, but CODE allows you to explictly name the section, which
is a good idea.

>        movwf   w_temp

This is wrong without a guarantee that W_TEMP is either in unbanked memory
or reserved at the same offset in every bank.

>        movf    STATUS,w
>        movwf   status_temp

Without explicitly setting the banks between these two instructions, you
have to reserve STATUS_TEMP the same was as W_TEMP.  A better way is to
insert a CLRF STATUS between these two instructions.  Then STATUS_TEMP goes
in regular bank 0.

> ; isr code can go here or be located as a call subroutine elsewhere

It should be located here.  Some code will end up here, so it might as well
be the one routine that benefits from being at this location.  Doing a CALL
uses up a call stack slot that can't be used by the foreground code.

You also need to pay attention to PCLATH.  On machines with more than one
code page you need to save PCLATH then clear it, else local GOTO's in the
interrupt routine won't work as expected.  Since this is easy to forget, so
it's better to have your interrupt routine template include assembly time
conditional code for saving/restoring PCLATH based on whether the current
PIC has multiple code pages or not.

>        movf    status_temp,w
>        movwf   STATUS
>        swapf   w_temp,f
>        swapf   w_temp,w
>        retfi

That should be RETFIE.

Interrupt routines are a solved problem.  There is no need to reinvent the
wheel.  You can use or modify my QQQ_INTR.ASPIC interrupt routine template
that is part of my PIC develpment environment at
http://www.embedinc.com/pic.  It contains various assembly time conditionals
to configure itself to different 14 bit core PICs.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\07\01@101200 by Nicola Perotto

picon face
Hi Rolf,
try this code:

   clrf    STATUS           ;not really 0!
   clrf       X                    
   movf    X,w                
   movf    STATUS,w

   nop

   movwf    X
   movf    STATUS,W

If you trace with MP SIM you see that the Z flag is changed!
Cheers
       Nicola


Rolf wrote:
{Quote hidden}

2008\07\01@105005 by Tamas Rudnai

face picon face
>   clrf    STATUS           ;not really 0!

This one sets the Z even if there are non-writeable flags in STATUS.

Question is that when can be the STATUS completely 0, as !TO and !PD for
instance likely to be 1, !TO can be zero after WDT but !PD is only when in
sleep mode. So MOVF might do, except if anyone knows when and how can be the
STATUS cooled down to absolute zero :-)

Tamas
PS: Still, there is no reason not to use SWAPF in my opinion, there is no
harm with that...



On Tue, Jul 1, 2008 at 3:09 PM, Nicola Perotto <RemoveMEnicolaTakeThisOuTspamnicolaperotto.it>
wrote:

{Quote hidden}

>

2008\07\01@110836 by olin piclist

face picon face
Rolf wrote:
> Two things... First, I am confused. I though newbies (like me) should
> download your development environment ...

No.  I have never suggested it as a starting point.  There is too much there
to learn beyond just the PIC and MPASM/MPLIB/MPLINK.  Once someone is
familiar with the PIC and tools, then they can possibly use my PIC
development environment.  I don't care if they do, but it's there for free
for anyone that wants to.

> Secondly, Explicitly writing BSF/BCF on RP0/RP1 *IS* encouraged.
> ...
> In fact, the datasheet
> (which you disagree with) explicitly recommends it in the ISR.

No, the data sheet doesn't recommend or encourage any particular style of
programming.  Occasionally small snippets of code are shown in the data
sheet to illustrate points.  These are not meant as good examples of
programming, and usually aren't.  They are usually just the bare minimum
instructions to perform whatever action they are describing.

> You have now suggested three different solutions to one problem. First
> you said I should do a clrf STATUS.

Yes, in the one specific case in the interrupt routine.  I couldn't fault
anyone for using BANKSEL there instead, which I even pointed out.

> Then you said I should always use banksels.

That is the absolutely safe approach everyone should start with.  Some may
never get beyond that.  That's OK.  BANKSEL is never wrong, only less
efficient than more advanced techniques like my macros that track the bank
setting at assembly time.

> Finally, you are suggesting I use your macros.

No, only making them available and sometimes referring to how they work.

However, BSF/BCF on RP0/RP1 is bad programming practise.  That's the one
thing you should definitely not do.

Look, you can do what you want.  I have no reason to care.  You can ignore
all the advice you get here.  My programs will still run fine.  However, I
don't want anyone else listening in to pick up bad habits and think that
direct manipulation of the bank bits is somehow acceptable programming
practise.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\07\01@113634 by Rolf

face picon face
Thanks Olin.

But, the basic question has not been answered...

The question is whether the .asm templates from Microchip for the
PIC12F675 successfully save and restore STATUS and W registers.

I believe they do, Tamas believes they don't (I think he believes that
anyway, as well as perhaps some others).

Here is the code, again.... as copied / pasted from the file
12F675TEMP.ASM file distributed by Microchip (this time with the
trailing 'e').

       ORG     0x004             ; interrupt vector location
       movwf   w_temp            ; save off current W register contents
       movf    STATUS,w          ; move status register into W register
       movwf    status_temp       ; save off contents of STATUS register


; isr code can go here or be located as a call subroutine elsewhere


       movf    status_temp,w     ; retrieve copy of STATUS register
       movwf    STATUS            ; restore pre-isr STATUS register
contents
       swapf   w_temp,f
       swapf   w_temp,w          ; restore pre-isr W register contents
       retfie                    ; return from interrupt

As has been suggested numerous times by others, there are other ways to
do the same thing (and I have changed my code as well). The question is,
whether, on the PIC12F675, the above actually works?

Yes, No, if not, then why...?

It is only 8 instructions, and, if it does not work then there is
something I have missed in my understanding of the individual
instructions, MPSIM, and more.

Rolf


2008\07\01@134413 by Jan-Erik Soderholm

face picon face
Rolf wrote:

>         ORG     0x004             ; interrupt vector location
>         movwf   w_temp            ; save off current W register contents
>         movf    STATUS,w          ; move status register into W register
>         movwf    status_temp       ; save off contents of STATUS register
>

They key point here (and also what I *think* that Tamas
has got wrong) is that MOVWF does *not* change the Z-flag.
It doesn't change any STATUS flags. Thats why the code
*does* work, even without any SWAPF's in the code above.

Below, OTOH, SWAP *must* be used, since MOVF (either to "W"
or to "F") *does* set/clear the Z-flag.

Jan-Erik.


{Quote hidden}

2008\07\01@135545 by Jan-Erik Soderholm

face picon face
I would just like to add that, *of course*
are w_temp and status_temp allocated from
the "share bank" (or "unbanked memory").

Jan-Erik.

Jan-Erik Soderholm wrote:
{Quote hidden}

2008\07\01@140123 by Nicola Perotto

picon face
Jan-Erik (he reads always the f manual ;-) is right!
The point is that the first MOVF works but the second not, so you MUST
use the SWAPF in the second position.
But if you use the SWAPF in the second position you expect a swapped
data! So you need the SWAPF also in the first position.
     Nic


Jan-Erik Soderholm wrote:
{Quote hidden}

2008\07\01@140357 by Tamas Rudnai

face picon face
> They key point here (and also what I *think* that Tamas
> has got wrong) is that MOVWF does *not* change the Z-flag.

Sorry I did not say that :-) I said MOVF changes the Z. Also said that as
there are at least two flags in STATUS that are not writable and have no
idea when and what circumstances both of them get cleared MOVF as saving the
STATUS might work (as STATUS will never be completely zero). And also said
:-) that I think it is safer to use SWAPF and there is no any reason not to
use that.

Tamas




On Tue, Jul 1, 2008 at 6:43 PM, Jan-Erik Soderholm <
TakeThisOuTjan-erik.soderholmEraseMEspamspam_OUTtelia.com> wrote:

{Quote hidden}

> -

2008\07\01@142609 by Jan-Erik Soderholm

face picon face
Tamas Rudnai wrote:

> Also said that as
> there are at least two flags in STATUS that are not writable and have no
> idea when and what circumstances both of them get cleared MOVF as saving
> the STATUS might work...

Can you show a case when it *does not* work ?
Or are you guessing ?

> (as STATUS will never be completely zero).

Even so, Z would have been set *after* STATUS is saved,
so that doesn't matter.

> And also said
> :-) that I think it is safer to use SWAPF and there is no any reason not to
> use that.

Right, first show a case when the shown example goes wrong.

I've not looked into it fully, but doesn't SWAP's
add a few (one?) extra instruction(s) ? Since this is in the
ISR-overhead, I'd care about that.

*OR*, use a PIC18 and the automatic shadow regs... :-)

Jan-Erik.

2008\07\01@144602 by Rolf

face picon face

With the PIC12F675, the datasheet states:

The data memory (see Figure 2-2) is partitioned into
two banks, which contain the General Purpose regis-
ters and the Special Function registers. The Special
Function registers are located in the first 32 locations of
each bank. Register locations 20h-5Fh are General
Purpose registers, implemented as static RAM and are
mapped across both banks.

This is somewhat ambiguous, but, addresses 20h through 5Fh are all in
'bank 0'. The concept of being mapped across 'both banks' is illustrated
better in the Figure 2-2 which indicates, in Bank 1 that addresses A0h
through DFh access 20h through 5Fh respectively.

Further, the mid-range reference manual has the following:

Some Mid-Range MCU devices have banked memory in the GPR area. GPRs are
not initialized
by a Power-on Reset and are unchanged on all other resets.
The register file can be accessed either directly, or using the File
Select Register FSR, indirectly.
Some devices have areas that are shared across the data memory banks, so
a read / write to
that area will appear as the same location (value) regardless of the
current bank. We refer to this
area as the Common RAM.

I presume it is safe to suggest that the 12F675 is one of the 'Common
RAM' devices, where ALL GPR memory is common, (but the 32 SFR addresses
in each bank are not).

Hence, I presume this confirms that there is no need to do banking for
GPR memory for the PIC12F675 (but I am sure that Olin will suggest that
is bad practice if I were to copy/paste the code to another device.... ;-)

Rolf

Jan-Erik Soderholm wrote:
{Quote hidden}

2008\07\01@144731 by Bob Ammerman

picon face

>       ORG     0x004
>       movwf   w_temp        - could go in either bank!
>       movf    STATUS,w
>       movwf    status_temp    -- could go in either bank!
> ; isr code can go here or be located as a call subroutine elsewhere
>       movf    status_temp,w    -- you're dead if the bank has changed!
>       movwf    STATUS
>       swapf   w_temp,f
>       swapf   w_temp,w
>       retfi

The above code requires a 'shadow' of w_temp in all banks.
It also requires a shadow of 'status_temp' in all banks, which shouldn't be
needed.
It also requires that the banking status be saved/restored separately, which
is a pain.

Code that works:

   org    0x4
   movwf    w_temp            ; either bank!
   movf       STATUS,w      ; ok: clobbers Z, but saves STATUS first
   bcf          STATUS,RP0  ; ** add this **
-or-
   clrf          STATUS          ; ** or this **
   movwf    status_temp       ; certain to be in bank 0

<your isr code here>
<make sure you are (back) in bank 0>

   movf       status_temp,W    ; ok: clobbers Z, but W contains original
value of status
   movwf    STATUS            ; ok: bank is now what it was at interrupt
entry
   swapf      w_temp,F          ; ok: no flags changed, could be in either
bank


-- Bob Ammerman
RAm Systems

   swapf      w_temp,W         ; ok: no flags changed, could be in either
bank
   retfi


---Bob Ammerman
RAm Systsems



2008\07\01@145650 by Tamas Rudnai

face picon face
> Can you show a case when it *does not* work ?
> Or are you guessing ?

Nope, I can't. I am guessing about STATUS, that STATUS never goes to zero
(as !TO and/or !PD) will always set - that's my guessing and coul dnot find
any info about a situation when it would be the case. The problem with MOVF
is that it depends on this guessing, that STATUS never goes zero
completely...

> Even so, Z would have been set *after* STATUS is saved,
> so that doesn't matter.

I see what you mean. I saw many interesting behaviours, like if you have the
FSR on a 10F202 and INCFSZ on it, FSR never goes to zero as the 3 higher
bits are always read as zero, however, INCFSZ skips the next instrution if
FSR previously was 0xFF. It means for me that actually the status checked
_before_ the incrementation would be made - in other words the micro code of
the PIC checks if the register was FF before the incrementation instead of
checking if that was 0 after it.

Because of this experience I would not be surprised if Z would set before
the move had been done. Other words I would not be surprised if microcode
checks first if STATUS is zero, then sets Z (in STATUS) then moves STATUS to
W (with the Z already set)...

> I've not looked into it fully, but doesn't SWAP's
> add a few (one?) extra instruction(s) ? Since this is in the
> ISR-overhead, I'd care about that.

All you have to do is _instead_ of MOVF use SWAPF... both of them 1 word / 1
cycle, so no harm in my opinion.

Tamas







On Tue, Jul 1, 2008 at 7:25 PM, Jan-Erik Soderholm <
RemoveMEjan-erik.soderholmspamTakeThisOuTtelia.com> wrote:

{Quote hidden}

> -

2008\07\01@145740 by Bob Ammerman

picon face
'Cooling' status down to 'absolute zero':

   clrf    STATUS
   bcf    STATUS,Z


OR:

   movlw    0
   movwf    STATUS

I don't believe there is a one instruction way to do this.

-- Bob Ammerman
RAm Systems

2008\07\01@145802 by Tamas Rudnai

face picon face
Correcting myself

> as the 3 higher bits are always read as zero

as the 3 higher bits are always read as ONE of course

Tamas


On Tue, Jul 1, 2008 at 7:56 PM, Tamas Rudnai <tamas.rudnaiEraseMEspam.....gmail.com> wrote:

{Quote hidden}

>> --

2008\07\01@150426 by Jan-Erik Soderholm

face picon face
Rolf wrote:

> Hence, I presume this confirms that there is no need to do banking for
> GPR memory for the PIC12F675

Correct. Or for the PIC12F629.

(And I was the one who discovered that Olins environment
didn't support "only-nonbanked-GPR" PICs, several years ago :-)
That is, the 12F675/629 types...)

> (but I am sure that Olin will suggest that
> is bad practice if I were to copy/paste the code
> to another device....

Or if you simply decide to use the 12F683 instead.
That one has both banked and unbanked GPR's... :-)

Jan-Erik.

2008\07\01@155914 by olin piclist

face picon face
Rolf wrote:
> I presume it is safe to suggest that the 12F675 is one of the 'Common
> RAM' devices, where ALL GPR memory is common, (but the 32 SFR
> addresses in each bank are not).

Yes, it appears to be one of those.

> Hence, I presume this confirms that there is no need to do banking for
> GPR memory for the PIC12F675

It means all your variables only live in bank 0.  They are also aliased from
bank 1, and that PIC only has banks 0 and 1, so you don't need to worry
about banking when accessing a variable in RAM.

However, don't get to used to that.  Most PICs don't work that way.  It's a
good idea to learn the discipline the right way even if you could get away
with being more sloppy in this case.

You can define all your variables in a UDATA_SHR section.  That states that
they must go in shared memory.  If the code is ever built for a PIC that
doesn't have that much shared memory, you will get build errors.  Then you
can inspect the variables and decide how to move them around and add the
necessary bank switching code.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\07\01@172756 by Jan-Erik Soderholm
face picon face
Tamas Rudnai wrote:

> Because of this experience I would not be surprised if Z would set before
> the move had been done. Other words I would not be surprised if microcode
> checks first if STATUS is zero, then sets Z (in STATUS) then moves STATUS to
> W (with the Z already set)...

I would be surpriced.
It would probably break a lot of code depending
on the bits beeing updated after the move.

Jan-Erik.

2008\07\01@182128 by Tamas Rudnai

face picon face
You were right Jan, MOVF is not strange at all and works as expected. Tried
the following code on MPSIM compiled for 12F683, and I think MPSIM is good
enough simulator to believe that this is correct on real MCU as well:

start
       movlw    0
       movwf    STATUS    ; clears all flags except !TO and !PD

       sleep              ; clears !PD
       nop                ; after WDT !TO cleared as well

       ; now STATUS is absolute 0x00

       movf     STATUS,w  ; sets Z but W will be 0x00
       movwf    STATUS    ; STATUS remains 0x00

       goto    start

So the conclusion is that I was wrong, we can safely use MOVF to save STATUS
- sorry for my skepticism.

Tamas



On Tue, Jul 1, 2008 at 10:27 PM, Jan-Erik Soderholm <
RemoveMEjan-erik.soderholmEraseMEspamEraseMEtelia.com> wrote:

{Quote hidden}

> -

2008\07\01@194536 by Jinx

face picon face
> Assembler appears to be somewhat like perl, TIMTOWTDI ... ;-)
>
> There Is More Than One Way To Do It - this is the perl 'mantra'

The big difference of course is that you're working right down at the
chip level. I suggest that to do many things in firmware in machine
code there is only one way to do it correctly and reliably

2008\07\01@213653 by Matthew Miller

flavicon
face
I'm still reading the thread, but I wanted to post the ISR code that I use,
since that seems to be what the discussion is most about. This code is due
to Fr. McGee (I think!) and it has always worked with the 16F and 12F parts
I use. Here you go:

       ; The ISR begins here at program location 0x04.
       movwf   w_temp      ; copy W to temp register
       swapf   STATUS, W   ; swap status to be saved into W
       movwf   status_temp

       movf    PCLATH, W
       movwf   pclath_temp

       movf    FSR, W
       movwf   fsr_temp

       ; ISR goes here...

leave_isr
       movf    fsr_temp, W
       movwf   FSR
       movf    pclath_temp, W
       movwf   PCLATH
       swapf   status_temp, W  ; swap STATUS_TEMP register into W, sets bank to original state
       movwf   STATUS          ; move W into STATUS register
       swapf   w_temp, F       ; swap w_temp
       swapf   w_temp, W       ; swap W_TEMP into W
       retfie

Best wishes Rolf.

--
"You're one of those condescending Unix computer users!"
"Here's a nickel, kid.  Get yourself a better computer" -- Dilbert.

2008\07\02@042615 by Alan B. Pearce

face picon face
>I've not looked into it fully, but doesn't SWAP's
>add a few (one?) extra instruction(s) ? Since this is in the
>ISR-overhead, I'd care about that.

This is the trick - to use swapf STATUS,w instead of movwf STATUS at the
entry of the routine, so status gets stored with the two nybbles swapped.
Then at the end of the routine only one SWAPF is needed instead of two,
thereby saving an instruction in the ISR.

2008\07\02@070722 by olin piclist

face picon face
Matthew Miller wrote:
> ... but I wanted to post the ISR code that ...
> it has always worked with the 16F and 12F parts

Note that the 12 bit core parts don't have interrupts, so the 12F part you
refer to are really misnamed 14 bit core parts.

>         ; The ISR begins here at program location 0x04.
>         movwf   w_temp      ; copy W to temp register

You didn't show how the variables were defined.  W_TEMP must be in unbanked
memory or multiply defined at the same offset in every bank.

>         swapf   STATUS, W   ; swap status to be saved into W

You should insert a CRLF STATUS here.  That selects a predictable bank.  If
not then you either have to reserve STATUS_TEMP, PCLATH_TEMP and FSR_TEMP in
unbanked memory or at the same offset in all banks.  Unbanked memory is
usually precious, and reserving the same variable in multiple banks is a
waste.

>         movwf   status_temp
>
>         movf    PCLATH, W
>         movwf   pclath_temp
>
>         movf    FSR, W
>         movwf   fsr_temp

I put assembly time conditionals around saving PCLATH and FSR so that they
only get saved/restored when appropriate.  Also, you forgot to clear PCLATH
after saving it.

>         ; ISR goes here...
>
> leave_isr

Another CLRF STATUS and FSR_TEMP, PCLATH_TEMP, and STATUS_TEMP can be in
bank 0.

>         movf    fsr_temp, W
>         movwf   FSR
>         movf    pclath_temp, W
>         movwf   PCLATH
>         swapf   status_temp, W  ; swap STATUS_TEMP register into W,
>         sets bank to original state movwf   STATUS          ; move W
>         into STATUS register swapf   w_temp, F       ; swap w_temp
>         swapf   w_temp, W       ; swap W_TEMP into W
>         retfie

This got garbled so I didn't look at it closely.

Again, a 14 bit core interrupt routine is a solved problem.  Even if you're
not using my PIC development environment (http://www.embedinc.com/pic), you
can mostly copy my interrupt template routine QQQ_INTR.ASPIC.  It has all
the details taken care of.  Too many of you are trying to reinvent the
wheel, and then getting it wrong on top of it.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2008\07\02@193231 by David Meiklejohn

face
flavicon
face
Olin Lathrop wrote:

> You should insert a CRLF STATUS here.  That selects a predictable bank.
> If
> not then you either have to reserve STATUS_TEMP, PCLATH_TEMP and FSR_TEMP
> in
> unbanked memory or at the same offset in all banks.  Unbanked memory is
> usually precious, and reserving the same variable in multiple banks is a
> waste.

Certainly reserving the same variables in multiple banks would be
wasteful, but as to how precious unbanked memory - surely it depends?
It seems to me that using shared memory for context saving is quite valid.
It's true that it only costs one instruction (CLRF STATUS) to use bank 0,
but I still think that using shared registers is a valid choice, if they
are available - especially on a MCU like the 12F675 (the subject of this
thread) where all the GPRs are shared.


David Meiklejohn
http://www.gooligum.com.au

2008\07\02@195524 by Matthew Miller

flavicon
face
On Wed, Jul 02, 2008 at 07:09:34AM -0400, Olin Lathrop wrote:
>
> Also, you forgot to clear PCLATH after saving it.

Oh, this is a big one! All the locations in the previous post are in the
global bank, but me not clearning PCLATH is a mistake.

Olin, thanks for your comments and looking over this code that I posted. I'm
just a hobbyist, but I've learned some things from your post and this
thread.

Matthew

2008\07\03@034857 by Alan B. Pearce

face picon face
>Certainly reserving the same variables in multiple banks would be
>wasteful, but as to how precious unbanked memory - surely it depends?
>It seems to me that using shared memory for context saving is quite valid.

You need only 1 byte in shared memory for the interrupt variable save - the
one that saves W. The rest can go in bank 0 if you use Olins instruction
sequence (and I believe this instruction sequence has long been advocated by
Microchip as well).

2008\07\03@063221 by David Meiklejohn

face
flavicon
face
Alan B. Pearce wrote:
>
> >Certainly reserving the same variables in multiple banks would be
> >wasteful, but as to how precious unbanked memory - surely it depends?
> >It seems to me that using shared memory for context saving is quite
> valid.
>
> You need only 1 byte in shared memory for the interrupt variable save -
> the
> one that saves W. The rest can go in bank 0 if you use Olins
> instruction
> sequence

Yep, completely understand that, don't disagree - just saying that, if
enough shared registers are available, using them to save context is a valid
choice.

> (and I believe this instruction sequence has long been
> advocated by Microchip as well).

Perhaps, but here's a quote from the 16F887 data sheet (quite recent, from
2007):

"Since the upper 16 bytes of all GPR banks are common
in the PIC16F882/883/884/886/887 (see
Figures 2-2 and 2-3), temporary holding registers,
W_TEMP and STATUS_TEMP, should be placed in
here. These 16 locations do not require banking and
therefore, make it easier to context save and restore."

Now, I'm NOT saying that just because that's what's recommended in the data
sheet, it's what you have to do.  Just that Microchip seems to agree with me
that using shared registers is reasonable.


David Meiklejohn
http://www.gooligum.com.au



2008\07\03@070641 by Tamas Rudnai

face picon face
> "Since the upper 16 bytes of all GPR banks are common
> in the PIC16F882/883/884/886/887 (see

That's true, however, the only consideration is that sometimes you can use
the common area for optimized RAM usage - aka to avoid using bank selection
code outside of your isr (inside you use the bank0 with Olin's suggestion
anyway, so there is no need to waste the common area).

Tamas



On Thu, Jul 3, 2008 at 11:31 AM, David Meiklejohn <RemoveMEdavidspam_OUTspamKILLspamgooligum.com.au>
wrote:

{Quote hidden}

> -

2008\07\03@072957 by Jan-Erik Soderholm

face picon face


Tamas Rudnai wrote:
>> "Since the upper 16 bytes of all GPR banks are common
>> in the PIC16F882/883/884/886/887 (see
>
> That's true, however, the only consideration is that sometimes you can use
> the common area for optimized RAM usage - aka to avoid using bank selection
> code outside of your isr (inside you use the bank0 with Olin's suggestion
> anyway, so there is no need to waste the common area).
>
> Tamas
>

OTOH, it's often in the ISR that you'd like to save
every cycle possible. So *I* do not see the usage of
shared memory in the ISR as "waste"...

Jan-Erik.

More... (looser matching)
- Last day of these posts
- In 2008 , 2009 only
- Today
- New search...