Browse Source

Display support

Stan Janssen 6 years ago
parent
commit
8d2d378103
1 changed files with 534 additions and 94 deletions
  1. 534 94
      minimalmode3.asm

+ 534 - 94
minimalmode3.asm

@@ -1,5 +1,4 @@
     list p=18f25k22
-    errorlevel -306 ; no page boundary warnings
     errorlevel -305 ; no default destination messages
     errorlevel -302 ; no bank 0 warnings
     errorlevel -202 ; no 'argument out of range' warnings
@@ -50,15 +49,27 @@
     config EBTR3 = OFF
     config EBTRB = OFF
 
-
+; Holding registers for some values
 CONTMR	    equ 000
 CPSTATE     equ 001
 DLYCOUNT    equ 002
 
-PILOT_12    equ 0F4
-PILOT_9     equ 0D2
-PILOT_6     equ 0B4
-DIODE_OK    equ 0B
+LCD_CHAR    equ 003
+LCD_NIB_H   equ 004
+LCD_NIB_L   equ 005
+
+DLYREG1     equ 006
+DLYREG2     equ 007
+
+WTEMP       equ 008
+
+PWM_VALUE   equ 009
+
+; Some constants
+PILOT_12  equ 0F4
+PILOT_9   equ 0D2
+PILOT_6   equ 0B4
+DIODE     equ 016
 
 PWM_6A      equ 19
 PWM_7A      equ 1D
@@ -71,8 +82,26 @@ PWM_13A     equ 36
 PWM_14A     equ 3A
 PWM_15A     equ 3E
 PWM_16A     equ 42
+PWM_0A      equ 0FA
+
+; Some port labels
+LCD_BL      equ 0
+LCD_RS      equ 3
+LCD_RW      equ 4
+LCD_EN      equ 5
 
-CHARGEPWM   equ PWM_8A
+; Return codes for the read_cp functions
+STATE_A     equ 0
+STATE_B     equ 1
+STATE_C     equ 2
+
+KNOP_LINKS  equ 0
+KNOP_MIDDEN equ 1
+KNOP_RECHTS equ 2
+
+CHARGEPWM   equ PWM_7A
+
+    goto    start
 
 start
     ; Initialize Ports                          TRISA
@@ -106,11 +135,12 @@ start
     ; PORTB, 5 = Richtingsschakelaar voor RS485 = digital out
     ; PORTB, 6 = UART 2 TX (moet als input)
     ; PORTB, 7 = UART 2 RX (moet als input)
-    
+
+    clrf    ANSELB
     movlw   b'11000000'
     movwf   TRISB
     
-    ; PORTC, 0 = display 5 = digital out
+    ; PORTC, 0 = display 5 = digital out (display verlichting)
     ; PORTC, 1 = Lock State = digital input
     ; PORTC, 2 = PWM output poort (moet als input geconfigureerd voor PWM operatie, pag 186)
     ; PORTC, 3 = display 6 = digital out
@@ -118,7 +148,8 @@ start
     ; PORTC, 5 = display 8 = digital out
     ; PORTC, 6 = UART 1 TX, RS485 communicatie TX 
     ; PORTC, 7 = UART 2 RX, RS485 communicatie RX
-    
+
+    clrf    ANSELC   
     movlw   b'11000110'
     movwf   TRISC
  
@@ -133,7 +164,7 @@ start
     movlw   0F9h                        ; Stel periode in op 249 = 1 kHz bij 16 MHz
     movwf   PR2
     
-    movlw   0FA                         ; Stel 100% PWM in bij start
+    movlw   PWM_0A                      ; Stel 100% PWM in bij start
     movwf   CCPR1L
     
     bcf     PIR2, TMR2IF
@@ -157,13 +188,30 @@ start
 ;    16      26.7%       267                     66          3
 
     ; Initialize TMR0 to use as a delay timer
-    ; Set to 16 bits, instruction cycle clock, use prescaler, use 4x prescaler
+    ; Set to 16 bits, instruction cycle clock, use prescaler, use 8x prescaler
     clrf    TMR0L
     clrf    TMR0H
     clrf    T0CON
+    bsf     T0CON, T0PS1
     
-    ; Always attempt to unlock on reset
-    call unlock
+    ; Initialize Serial port 2 (UART)
+    
+    bcf     TXSTA2, SYNC        ; Asynchronous
+    bsf     TXSTA2, BRGH        ; High speed
+    bcf     BAUDCON2, BRG16     ; 8 bit Baud Rate Generator
+    movlw   33                  ; 19.2 kbaud
+    movwf   SPBRG2
+    bsf     TXSTA2, TXEN        ; Enable the transmit port
+    bsf     RCSTA2, SPEN        ; Enable the receive port
+    bsf     RCSTA2, CREN        ; Enable continuous receive
+    
+    ; Initialize LCD
+    call    delay100
+    call    lcd_init
+    
+    movlw   PWM_7A
+    movwf   PWM_VALUE
+    call    display_7a
 
 
 ; Main application
@@ -183,9 +231,14 @@ enter
     movwf   CCPR1L
     
 
+
 idle
-    call    read_cp_high     ; Check if there is a car
-    sublw   0
+    call    display_idle
+    bcf     PORTC, LCD_BL   ; Turn off LCD backlight
+    call    check_serial    ; Check for serial communications
+    call    check_state     ; Check if there is a car
+    call    check_knoppen
+    sublw   STATE_A
     btfsc   STATUS, Z
     goto    enter
     
@@ -199,128 +252,141 @@ idle
 
 
 connected
+    call    check_knoppen
+    bsf     PORTC, LCD_BL    ; Turn on LCD backlight
+    
+    call    check_state
+    sublw   STATE_A
+    btfsc   STATUS, Z
+    goto    enter
+    
     btfsc   PORTC, 1    ; Check if the lock is closed
     goto    lock
     
-    movlw   CHARGEPWM      ; Start offering
-    movwf   CCPR1L
+    call    display_connected
+    movff   PWM_VALUE, CCPR1L
+    call    delay_1
     
     ; Check if the diode is OK
-;    call    read_cp_low      ; Check the diode
-;    sublw   3
-;    btfss   STATUS, Z        ; The return value must be 3, otherwise go back to enter.
-;    goto    enter
-    
+    call    check_diode      ; Check the diode (als goed: W = 1)
+    sublw   1                ; (W = 0)
+    btfss   STATUS, Z        ; Proceed if the diode state was 1
+    goto    enter
+
     ; Check the S2 state of the vehicle
-    call    read_cp_high
+    call    check_state
+    
     movwf   CPSTATE
-    sublw   1           ; Cable still connected?
+    sublw   STATE_B
     btfsc   STATUS, Z
     goto    connected
     
     movf    CPSTATE, w
-    sublw   2           ; Charging requested?
+    sublw   STATE_C
     btfsc   STATUS, Z
     goto    charging
     
-    ; Cable must be disconnected, unlock and go back to idle.
     goto    enter
-
+    
+    
 charging
+    call    display_charging
+    movff   PWM_VALUE, CCPR1L
     bsf     PORTB, 4           ; Power On
-    
-    call    read_cp_high
-    movwf   CPSTATE
-    sublw   2                   ; Still charging?
+
+    call    check_knoppen    
+    call    check_state
+    sublw   STATE_C
     btfsc   STATUS, Z
     goto    charging
     
     bcf     PORTB, 4            ; Power Off
     goto    connected
-    
 
 
-read_cp_high
+check_state
     ; Lees CP uit en return met een waarde in W (0 = los, 1 = connected, 2 = S2 gesloten)
-    ;    PILOT_12  = 0F4
-    ;    PILOT_9   = 0D2
-    ;    PILOT_6   = 0B4
 
     ; TMR2 loopt mee gedurende de PWM. Als TMR2 < CCPR1L dan zitten we nog in de hoog periode.
-    ; De aquisitietijd voor de AD-conversie is 4 cycli. Als we 16 cycli voor het eind van de PWM-hoog periode beginnen met samplen, hebben we tijd genoeg.
+    ; De aquisitietijd voor de AD-conversie is 4 cycli. Als we 8 cycli voor het eind van de PWM-hoog periode beginnen met samplen, hebben we tijd genoeg.
     ; We willen niet direct aan het begin van de periode zitten, maar na 5%.
-    ; Dus 12 < TMR2 < (CCPR1L - 16) 
+    ; Dus 12 < TMR2 < (CCPR1L - 8) 
     
     ; Check if TMR2 > 12d
     movlw   d'12'
-    subwf   TMR2, W             ; TMR2 - 12: moet > dan nul zijn, STATUS,C = 1
-    btfss   STATUS, C           ; Continue to next step if STATUS,C = 1
-    goto    read_cp_high
+    cpfsgt  TMR2            ; Compare TMR2 to W, proceed if TMR2 > W
+    goto    check_state
     
     ; Check if TMR2 < (CCPR1L - 16)
-    movlw   d'16'               ; 16 -> W
-    subwf   CCPR1L, W           ; (CCPR1L - 16) -> W
-    subwf   TMR2, W             ; TMR2 - (CCPR1L - 16): moet < dan nul zijn, STATUS,C = 0
-    btfsc   STATUS, C           ; Continue to next step if STATUS,C = 0
-    goto    read_cp_high
-    goto    take_sample
- 
-
-read_cp_low
-    ; Read the CP at the low point, return 3 if OK, 0 if not.
-    ; (CCPR1L + 12) < TMR2 < (PR2 - 16)
-    
-    ; Check if TMR2 > CCPR1L + 12
-    movf    CCPR1L, W           ; CCPR1L -> W
-    addlw   d'12'               ; (CCPR1L + 12) -> W
-    subwf   TMR2, W             ; TMR2 - (CCPR1L + 12): moet > dan nul, STATUS,C = 1
-    btfss   STATUS, C
-    goto    read_cp_low
-    
-    ; Check if TMR2 < (PR2 - 16)
-    movlw   d'16'               ; 16 -> W
-    subwf   PR2, W              ; (PR2 - 16) -> W
-    subwf   TMR2, W             ; TMR2 - (PR2 - 16): moet < dan nul zijn, STATUS,C = 0
-    btfsc   STATUS, C
-    goto    read_cp_low
-    goto    take_sample
-
-take_sample
-    bsf     ADCON0, GO          ; Start the sample
+    movlw   8                   ; 8 -> W
+    subwf   CCPR1L, W           ; (CCPR1L - 8) -> W
+    cpfslt  TMR2                ; Compare TMR2 to W, proceed if TMR2 < W
+    goto    check_state
     
-wait_for_ad_result
-    btfsc   ADCON0, DONE
-    goto    wait_for_ad_result
+    call    take_sample
+    movf    ADRESH, W
     
-    ; Check if 12V
+    ; Check if >12V
     movf    ADRESH, w       ; Voltage -> W
     sublw   PILOT_12        ; PILOT_12 - Voltage: moet < nul zijn, dus STATUS,C = 0
     btfss   STATUS, C
-    retlw   0
+    retlw   STATE_A
     
-    ; Check if 9V
+    ; Check if >9V
     movf    ADRESH, w
     sublw   PILOT_9
     btfss   STATUS, C
-    retlw   1
+    retlw   STATE_B
     
-    ; Check if 6V
+    ; Check if >6V
     movf    ADRESH, w
     sublw   PILOT_6
     btfss   STATUS, C
-    retlw   2
+    retlw   STATE_C
+
+    
+    ; If it is something else, take state A which is safe.
+    retlw   STATE_A
+
+check_diode
+    ; Read the CP at the low point, return 1 if OK, 0 if not.
+    ; (CCPR1L + 12) < TMR2 < (PR2 - 8)
+    
+    ; Check if TMR2 > CCPR1L + 12
+    movf    CCPR1L, W           ; CCPR1L -> W
+    addlw   d'12'               ; (CCPR1L + 12) -> W
+    cpfsgt  TMR2                ; Compare TMR2 to W, proceed if TMR2 > W
+    goto    check_diode
     
-    ; Check if diode OK
-    movf    ADRES, w            ; Voltage -> W
-    sublw   DIODE_OK            ; DIODE_OK - Voltage: moet > 0, STATUS,C = 1
-    btfsc   STATUS, C           ; Skip over this ff the STATUS,C = 0
-    retlw   3
+    ; Check if TMR2 < (PR2 - 8)
+    movlw   8                   ; 8 -> W
+    subwf   PR2, W              ; (PR2 - 8) -> W
+    cpfslt  TMR2                ; Compare TMR2 to W, proceed if TMR2 < W
+    goto    check_diode
+
+    call    take_sample
     
-    ; Otherwise return "0", meaning just go to idle and turn everything off
+    movlw   DIODE
+    cpfsgt  ADRESH              ; Compare ADRESH to DIODE, return 0 if ADRESH > DIODE
+    retlw   1
     retlw   0
 
 
+take_sample
+    bsf     ADCON0, GO          ; Start the sample
+
+wait_sample
+    btfsc   ADCON0, DONE
+    goto    wait_sample
+    return
+
+
+
+
+; Routines for locking and unlocking
+
 lock
+    call    display_lock
     bcf     PORTA, 4
     bsf     PORTA, 5
     call    delay100        ; Blocking 100ms delay
@@ -333,17 +399,29 @@ lock
 unlock
     movlw   0FA             ; Turn off PWM
     movwf   CCPR1L
+    bcf     PORTB, 4        ; Power off
+
+    call    display_unlock
     
-    bsf     PORTA, 4
+    bsf     PORTA, 4        ; Start the motor
     bcf     PORTA, 5
     call    delay100        ; Blocking 100ms delay
     call    delay100        ; Blocking 100ms delay
     bsf     PORTA, 5        ; Stop the motor
     
     call    delay2000       ; Wait 2 seconds to charge the capacitor back up.
-    goto    enter
+    goto    enter           ; Always go to 'enter' after unlocking.
+
+
+
+
+
+
+
 
 
+; Routines for a 100 ms delay
+
 delay100
     ; Preset timer 0 value at 15533
     movlw   3C
@@ -351,22 +429,19 @@ delay100
     movlw   0AD
     movwf   TMR0L
     
-    ; Set prescaler to 8x
-    bcf     T0CON, T0PS0
-    bsf     T0CON, T0PS1
-    bcf     T0CON, T0PS2
-    
     ; Start the timer
     bcf     INTCON, TMR0IF      ; Clear the interrupt
     bsf     T0CON, TMR0ON       ; Start the timer
-    goto    delay_wait
 
 delay_wait
     btfss   INTCON, TMR0IF       ; Wait for the timer to overflow
     goto    delay_wait
+    
     bcf     T0CON, TMR0ON        ; Stop the timer
     return
 
+; Routines for a 2 second delay
+
 delay2000
     movlw   d'20'
     movwf   DLYCOUNT
@@ -378,4 +453,369 @@ delay_repeat
     goto    delay_repeat
     return
 
+
+; Routines to handle serial communication from the Raspberry Pi
+
+check_serial
+    btfsc   PIR3, RC2IF     ; Check of er iets aan de hand is
+    goto    read_serial
+    return
+
+read_serial
+    btfsc   RCSTA2, FERR    ; Check of er een frame error is (dan naar reset)
+    goto    start_reset
+    
+    btfsc   RCSTA2, OERR    ; Check of er overrun-errors zijn en wis deze
+    call    clear_oerr
+    
+    movf    RCREG2, W
+    return
+
+clear_oerr
+    bcf     RCSTA2, CREN
+    bsf     RCSTA2, CREN
+    return
+
+start_reset
+    call    display_reset
+    reset
+
+display_reset
+    movlw   1
+    call    lcd_write
+    movlw   80
+    call    lcd_write
+    movlw   A'R'
+    call    lcd_print
+    movlw   A'E'
+    call    lcd_print
+    movlw   A'S'
+    call    lcd_print
+    movlw   A'E'
+    call    lcd_print
+    movlw   A'T'
+    call    lcd_print
+    return
+
+
+
+
+; 1 ms Delay (for display logic)
+
+delay_1
+    movwf   WTEMP
+    movlw   4
+    movwf   DLYREG1
+    movlw   0F8
+    movwf   DLYREG2
+    
+delay_1_inner
+    nop
+    decfsz  DLYREG2         ; 1 cycle
+    goto    delay_1_inner   ; 2 cycles
+
+delay_1_loop
+    movlw   0F8
+    movwf   DLYREG2
+    decfsz  DLYREG1
+    goto    delay_1_inner
+    movf    WTEMP, W
+    return
+
+
+
+
+; Everything having to do with the HD44780 display
+
+lcd_init
+    call    delay100
+    bcf     TRISB, KNOP_LINKS
+    bcf     TRISB, KNOP_MIDDEN
+    bcf     TRISB, KNOP_RECHTS
+    
+    bcf     PORTC, LCD_EN
+    bcf     PORTC, LCD_RW
+    bcf     PORTC, LCD_RS
+    
+    movf    PORTB, W
+    andlw   0F0
+    iorlw   3                   ; Reset instruction, see page 45 of Hitachi datasheet
+    movwf   PORTB
+    call    lcd_go
+    
+    call    delay_1             ; wait 5 ms
+    call    delay_1
+    call    delay_1
+    call    delay_1
+    call    delay_1
+    
+    call    lcd_go
+    call    delay_short
+    call    lcd_go
+    call    delay_short
+    
+    movf    PORTB, W
+    andlw   0F0
+    iorlw   2                   ; Set up as 4-bit mode (interpreted as 8-bit command so completes in one write)
+    movwf   PORTB
+    call    lcd_go
+    
+    call    delay_1             ; 4-bit transmissions starts here
+    
+    movlw   b'00101000'         ; Function Set, 4-bit, 2 line display, 5x8 pixel characters
+    call    lcd_write
+    
+    movlw   b'00001000'         ; Display Off, Cursor Off, Blink Off
+    call    lcd_write
+    
+    movlw   b'00000001'         ; Clear Display
+    call    lcd_write
+
+    movlw   b'00000110'         ; Entry mode set (increment and not shifted)
+    call    lcd_write
+   
+    movlw   b'00001100'         ; Display On, Blink On
+    call    lcd_write
+
+    bsf     TRISB, KNOP_LINKS
+    bsf     TRISB, KNOP_MIDDEN
+    bsf     TRISB, KNOP_RECHTS
+
+    return
+
+lcd_print
+    bsf     PORTC, LCD_RS
+    call    lcd_write
+    bcf     PORTC, LCD_RS
+    return
+
+lcd_write
+    ; Split nibbles
+    bcf     TRISB, KNOP_LINKS
+    bcf     TRISB, KNOP_MIDDEN
+    bcf     TRISB, KNOP_RECHTS
+    movwf   LCD_CHAR
+    andlw   0F
+    movwf   LCD_NIB_L
+
+    swapf   LCD_CHAR, W
+    andlw   0F
+    movwf   LCD_NIB_H
+
+    ; Write high nibble
+    movf    PORTB, W
+    andlw   0F0
+    iorwf   LCD_NIB_H, W
+    movwf   PORTB
+    call    lcd_go
+    call    delay_1
+    
+    ; Write low nibble
+    movf    PORTB, W
+    andlw   0F0
+    iorwf   LCD_NIB_L, W
+    movwf   PORTB
+    call    lcd_go
+    call    delay_1
+    call    delay_1
+    bsf     TRISB, KNOP_LINKS
+    bsf     TRISB, KNOP_MIDDEN
+    bsf     TRISB, KNOP_RECHTS
+    return
+
+lcd_go
+    bsf     PORTC, LCD_EN
+    nop
+    nop
+    bcf     PORTC, LCD_EN
+    return
+
+delay_short
+    decfsz  DLYREG1
+    goto    delay_short
+    return
+
+display_idle
+    movlw   80
+    call    lcd_write
+    movlw   A' '
+    call    lcd_print
+    movlw   A'G'
+    call    lcd_print
+    movlw   A'e'
+    call    lcd_print
+    movlw   A'r'
+    call    lcd_print
+    movlw   A'e'
+    call    lcd_print
+    movlw   A'e'
+    call    lcd_print
+    movlw   A'd'
+    call    lcd_print
+    
+    return
+    
+display_connected
+    movlw   80
+    call    lcd_write
+    
+    movlw   A'V'
+    call    lcd_print
+    
+    movlw   A'r'
+    call    lcd_print
+    
+    movlw   A'b'
+    call    lcd_print
+    
+    movlw   A'o'
+    call    lcd_print
+    
+    movlw   A'n'
+    call    lcd_print
+    
+    movlw   A'd'
+    call    lcd_print
+    
+    movlw   A'e'
+    call    lcd_print
+    
+    movlw   A'n'
+    call    lcd_print
+    
+    return
+
+display_charging
+    movlw   80
+    call    lcd_write
+    
+    movlw   A' '
+    call    lcd_print
+    
+    movlw   A'L'
+    call    lcd_print
+    
+    movlw   A'a'
+    call    lcd_print
+    
+    movlw   A'd'
+    call    lcd_print
+    
+    movlw   A'e'
+    call    lcd_print
+    
+    movlw   A'n'
+    call    lcd_print
+    
+    movlw   A' '
+    call    lcd_print
+    
+    movlw   A' '
+    call    lcd_print
+    
+    return
+
+display_unlock
+    movlw   80
+    call    lcd_write
+    
+    movlw   A' '
+    call    lcd_print
+    
+    movlw   A'U'
+    call    lcd_print
+    
+    movlw   A'n'
+    call    lcd_print
+    
+    movlw   A'l'
+    call    lcd_print
+    
+    movlw   A'o'
+    call    lcd_print
+    
+    movlw   A'c'
+    call    lcd_print
+    
+    movlw   A'k'
+    call    lcd_print
+    
+    movlw   A' '
+    call    lcd_print
+    
+    return
+    
+display_lock
+    movlw   80
+    call    lcd_write
+    
+    movlw   A' '
+    call    lcd_print
+    
+    movlw   A' '
+    call    lcd_print
+    
+    movlw   A'L'
+    call    lcd_print
+    
+    movlw   A'o'
+    call    lcd_print
+    
+    movlw   A'c'
+    call    lcd_print
+    
+    movlw   A'k'
+    call    lcd_print
+    
+    movlw   A' '
+    call    lcd_print
+    
+    movlw   A' '
+    call    lcd_print
+    
+    return    
+
+check_knoppen
+    btfss   PORTB, KNOP_LINKS
+    goto    set_7a
+    btfss   PORTB, KNOP_RECHTS
+    goto    set_14a
+    btfss   PORTB, KNOP_MIDDEN
+    goto    unlock
+    return
+
+set_7a
+    movlw   PWM_7A
+    movwf   PWM_VALUE
+    call    display_7a
+    return
+
+set_14a
+    movlw   PWM_14A
+    movwf   PWM_VALUE
+    call    display_14a
+    return
+
+display_7a
+    movlw   0C2
+    call    lcd_write    
+    movlw   A' '
+    call    lcd_print
+    movlw   A'7'
+    call    lcd_print
+    movlw   A'A'
+    call    lcd_print
+    return
+
+display_14a
+    movlw   0C2
+    call    lcd_write    
+    movlw   A'1'
+    call    lcd_print
+    movlw   A'4'
+    call    lcd_print
+    movlw   A'A'
+    call    lcd_print
+    return
+
     end