; PIC12F675 Configuration Bit Settings ; Assembly source line config statements ; CONFIG CONFIG FOSC = INTRCIO ; Oscillator Selection bits (INTOSC oscillator: I/O function on GP4/OSC2/CLKOUT pin, I/O function on GP5/OSC1/CLKIN) CONFIG WDTE = OFF ; Watchdog Timer Enable bit (WDT disabled) CONFIG PWRTE = ON ; Power-Up Timer Enable bit (PWRT enabled) CONFIG MCLRE = ON ; GP3/MCLR pin function select (GP3/MCLR pin function is MCLR) CONFIG BOREN = OFF ; Brown-out Detect Enable bit (BOD disabled) CONFIG CP = OFF ; Code Protection bit (Program Memory code protection is disabled) CONFIG CPD = OFF ; Data Code Protection bit (Data memory code protection is disabled) // config statements should precede project file includes. #include ; name GPIO bits used for TM1638 I/O STB equ 2 CLK equ 1 DIO equ 0 PSECT absdata, abs, ovrld, class=DATA, delta=1 ORG 20h sevenSeg: DS 8 ; 8 bytes of seven segment data left to right, common cathode leds: DS 1 ; 8 bits for the LEDS, left to right, 1 = illuminated buttons: DS 1 ; 8 bits for the 8 buttons, left to right, 1 = pressed ledMask: DS 1 ; masks all but one LED bit in refreshDisplay shiftReg: DS 1 ; byte being clocked in or out by read2Buttons or transmitByte i: DS 1 ; loop variable for refreshDisplay and read8Buttons loops j: DS 1 ; loop variable for transmitByte and read2Buttons loops msgStart: ; start index of displayed message ; in project properties, custom linker options add -presetVect=0 PSECT resetVect, class=CODE, delta=2 resetVect: ; PAGESEL(main) ; not needed on PIC12F, because it only has 1K Flash goto main PSECT myCode class=CODE, delta=2 transmitByte: ; clock out the byte passed in W movwf shiftReg BANKSEL(TRISIO) bcf TRISIO, DIO ; DIO pin is output BANKSEL(GPIO) bcf GPIO, STB ; enable TM1638 chip movlw 8 ; 8 bits to shift out movwf j ; loop variable tbLoop: ; shift out the bits from the least significant end bcf GPIO, CLK ; clock low btfss shiftReg, 0 bcf GPIO, DIO ; transmit a 0 if bit 0 of shiftReg is clear btfsc shiftReg, 0 bsf GPIO, DIO ; or transmit a 1 if bit 0 of shiftReg is set rrf shiftReg, F; shift next bit in place bsf GPIO, CLK ; TM1638 reads in bit on rising edge of clock decfsz j, F ; loop till 8 bits transmitted goto tbLoop return ; write 8 bytes from sevenSeg to TM1638 ; interspersed with 8 bytes set or cleared by the 8 bits of leds refreshDisplay: movlw 0x40 call transmitByte ; write display, auto increment bsf GPIO, STB ; end of command movlw 0xC0 call transmitByte ; set starting address zero. Note: no end of command here movlw sevenSeg movwf FSR ; file select register is pointer to sevenSeg movlw 8 ; 8 pairs of bytes to send movwf i ; loop variable movlw 0x80 movwf ledMask ; bits from most significant to least control the 8 leds rdLoop: movf INDF, W ; get one sevenSeg byte from table into w call transmitByte incf FSR, F ; advance pointer ready for next character (if any) movf leds, W andwf ledMask, W ; test if bit set btfss STATUS, 2 ; test Z bit: skip if W now contains 0 movlw 1 ; if ledMask bit was set in leds, W now contains 1 call transmitByte ; send 1 to switch LED on or 0 to switch off bcf STATUS, 0 ; clear carry, so next instruction can't set bit 7 rrf ledMask, F ; shift mask bit ready for next LED (if any) decfsz i, F ; loop to transmit 8 pairs of bytes goto rdLoop bsf GPIO, STB ; end of command return ; read 2 buttons from the TM1638 board into bits 0 and 4 of W. ; the way the board is laid out, first keyscan read returns the leftmost ; button (7) in bit 0 and the 5th button from right (3) in bit 4. ; subsequent auto-increment reads return buttons 6&2, 5&1, 4&0 the same bits read2Buttons: BANKSEL(TRISIO) bsf TRISIO, DIO ; DIO pin is input bsf WPU, DIO ; weak pull up enabled for DIO BANKSEL(GPIO) clrf shiftReg movlw 8 ; 8 bits to shift in movwf j ; loop variable r2bLoop: ; shift in the bits to the most significant end bcf GPIO, CLK ; clock low - TMS1638 outputs data on falling edge bcf STATUS, 0 ; clear carry rrf shiftReg, F btfsc GPIO, DIO bsf shiftReg, 7 ; move received bit into shiftReg bsf GPIO, CLK ; clock high decfsz j, F ; loop till 8 bits received goto r2bLoop movf shiftReg, W ; return 2 bits read in W return read8Buttons: ; read all 8 board pushbuttons into buttons byte movlw 0x42 ; read keyscan data, auto increment call transmitByte ; 2 microseconds needed after this, before 1st read clrf buttons movlw 4 ; four bytes to read movwf i ; loop variable r8bLoop: bcf STATUS, 0 ; clear carry rlf buttons, F ; shift any buttons already read (8-bit rotate, not 9) btfsc STATUS, 0 ; check what was bit 7 of buttons, now in carry bsf buttons, 0 ; rotate the bit back into buttons call read2Buttons ; read 2 buttons into bits 0 and 4 of W iorwf buttons, F ; merge those button bits with the ones already read decfsz i, F ; loop four times to read the 8 buttons goto r8bLoop swapf buttons, F ; after four shifts, nibbles are reversed bsf GPIO, STB ; end of communication return message: addwf PCL, F retlw 'A' retlw 'S' retlw ' ' retlw 'Y' retlw 'O' retlw 'U' retlw ' ' retlw 'C' retlw 'A' retlw 'N' retlw ' ' retlw 'S' retlw 'E' retlw 'E' retlw ' ' retlw 'T' retlw 'H' retlw 'E' retlw ' ' retlw 'P' retlw 'I' retlw 'C' retlw ' ' retlw '1' retlw '2' retlw 'F' retlw '6' retlw '7' retlw '5' retlw ' ' retlw 'I' retlw 'S' retlw ' ' retlw 'A' retlw ' ' retlw 'F' retlw 'I' retlw 'N' retlw 'E' retlw ' ' retlw 'U' retlw 'P' retlw 'R' retlw 'O' retlw 'C' retlw 'E' retlw 'S' retlw 'S' retlw 'O' retlw 'R' retlw '.' retlw ' ' retlw '.' retlw '.' retlw '.' retlw ' ' retlw '.' retlw '.' retlw '.' retlw ' ' retlw '.' retlw '.' retlw '.' retlw ' ' ; 64 byte message asciiTo7Seg: addlw -91 btfsc STATUS, 0 retlw 0 ; W was >= 91 : return blank addlw 91 - 45 ; W now original value - 45 btfss STATUS, 0; retlw 0 ; W was < 45 : return blank addwf PCL, F ; computed goto for 45 <= W <= 90 retlw 0x40 ; 45 - retlw 0x80 ; 46 . retlw 0x12 ; 47 / retlw 0x3F ; 48 0 retlw 0x06 ; 49 1 retlw 0x5B ; 50 2 retlw 0x4F ; 51 3 retlw 0x66 ; 52 4 retlw 0x6D ; 53 5 retlw 0x7D ; 54 6 retlw 0x07 ; 55 7 retlw 0x7F ; 56 8 retlw 0x6F ; 57 9 retlw 0x22 ; 58 : (") retlw 0x20 ; 59 ; (left apostrophe) retlw 0x39 ; 60 < ([) retlw 0x48 ; 61 = retlw 0x0F ; 62 > (]) retlw 0x53 ; 63 ? retlw 0x63 ; 64 @ (degree sign - high o) retlw 0x77 ; 65 A retlw 0x7C ; 66 B retlw 0x58 ; 67 C retlw 0x5E ; 68 D retlw 0x79 ; 69 E retlw 0x71 ; 70 F retlw 0x3D ; 71 G retlw 0x74 ; 72 H retlw 0x05 ; 73 I retlw 0x0D ; 74 J retlw 0x75 ; 75 K retlw 0x38 ; 76 L retlw 0x55 ; 77 M retlw 0x54 ; 78 N retlw 0x5C ; 79 O retlw 0x73 ; 80 P retlw 0x67 ; 81 Q retlw 0x50 ; 82 R retlw 0x6D ; 83 S (identical to 5) retlw 0x78 ; 84 T retlw 0x1C ; 85 U retlw 0x0C ; 86 V retlw 0x1D ; 87 W retlw 0x49 ; 88 X retlw 0x6E ; 89 Y retlw 0x5B ; 90 Z (identical to 2) loadDisplay: ; load 8 chars starting at message[W] to display movwf j ; index to message (wraps at length 64 back to 0) movlw 8 movwf i ; loop variable movlw sevenSeg movwf FSR ; file select register is pointer to sevenSeg ldLoop: movf j, W andlw 63 call message ; get ASCII char in W call asciiTo7Seg ; convert from ASCII to 7-segment movwf INDF ; write to sevenSeg incf FSR, F ; advance pointer to next display character incf j, F ; advance to next character of message decfsz i, F goto ldLoop return main: BANKSEL(CMCON) ; bank 0 clrf GPIO ; init GPIO (taken from datasheet example) movlw 7 movwf CMCON ; turn off comparitor BANKSEL(ANSEL) ; bank 1 clrf ANSEL ; switch A/D off bcf OPTION_REG, 7 ; enable pull-ups (required on DIO pin by read2Buttons) clrf TRISIO ; GPIO pns in output mode (except DIO is input for read2Buttons) BANKSEL(GPIO) ; bank 0 movlw 7 movwf GPIO ; all 3 outputs high, initially movlw 0x81 call transmitByte ; display off bsf GPIO, STB ; end of command movlw 0x88 call transmitByte ; set brightness 1_16 bsf GPIO, STB ; end of command clrf msgStart loop3: call read8Buttons movf buttons, W movwf leds movf msgStart, W call loadDisplay incf msgStart, F ; will go > 63, but refreshDisplay masks out top two bits call refreshDisplay clrf i clrf j delay1: decfsz j, F goto delay1 decfsz i, F goto delay1 goto loop3 END resetVect ; gives assembler clue to program start point. (Not needed PIC12)