; ------------------------------------------------------------- ; A PIC based version of the TRIKS-C "LEDTRIKS" driver board. ; ; Based reviews of the JEC Pixel FW, Renard FW, and Triks-C FW ; ; (c) 2009 Andrew Williams, Just Some Guy Productions ; ; ; Originally designed for the 16F688 ; ; PORT PIN DESCRIPTION ; ----------------------------- ; A0 13 SELECT_IN ; A1 12 AUTO_FEED ; A2 11 DATA_STROBE ; C0 10 DATA0 ; C1 9 DATA1 ; C2 8 DATA2 ; C3 7 DATA3 ; C4 6 SERIAL TX ; C5 5 SERIAL RX ; MCLR 4 ; A4 3 INIT ; A5 2 STATUS_LED ; GND 14 GND ; VCC 1 Vcc ; list p=16F688 ; list directive to define processor #include ; REMOVE THE EXTRA SPACES BETWEEN < and > - processor specific variable definitions errorlevel -302 ; suppress message 302 from list file __CONFIG _FCMEN_OFF & _IESO_OFF & _BOD_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_OFF & _WDT_OFF & _INTOSCIO ; OSC = INTOSCIO ; Watchdog = Disabled ; Power up Timer = Disabled ; MCLR = Reset ; Brownout = Disabled, SBODEN disabled ; Switchover = Disabled ; Failsave = Disabled ; Code = As needed ; EEPROM = As needed ; bits should be 30F4 ; ------------------- ; BANK0 Memory Block ; ------------------- CBLOCK 0x20 smSTATE ; ADDR of State Machine handler cmdPENDING ; Pending commands require a PAYLOAD to exist before ; we do anything, this variable records what command ; is "pending" when the payload is completly loaded. ; Value of the PENDING command ; Note PENDING_0 = PikC CONFIG ; PENDING_5 = Frame BANK0 ; PENDING_6 = Frame BANK1 payloadCount; # of bytes remaining to received in the payload. rxBYTE ; Command Byte received (not sure this is needed) pikcADDR ; For matching address from the TRIX-C commands gSTATUS ; 8 Bits of globals ; Top of "Image Frame" Fr0Row0:6 ; Point to start of the buffer Fr0Row1:6 Fr0Row2:6 Fr0Row3:6 Fr0Row4:6 Fr0Row5:6 Fr0Row6:6 Fr0Row7:6 Fr0End:0 ; Point to the end of the buffer, for reverse access ; Debug dumpChar ; Wait/Loop timer/counters COUNT timer end_bank_0_vars:0 ENDC if end_bank_0_vars > 0x70 error "Bank0 variable space overrun" endif ; ------------------- ; BANK 1 Memory Block ; ------------------- CBLOCK 0xA0 Fr1Row0:6 ; Point to start of the buffer Fr1Row1:6 Fr1Row2:6 Fr1Row3:6 Fr1Row4:6 Fr1Row5:6 Fr1Row6:6 Fr1Row7:6 Fr1End:0 ; Point to the end of the buffer, for reverse access end_bank_1_vars:0 ENDC if end_bank_1_vars > 0xF0 error "Bank1 variable space overrun" endif ; ------------------- ; Global Memory Block ; ------------------- CBLOCK 0x70 wsave ; Save W, STATUS, and PCLATH on entry to interrupt ssave psave fsrsave temp ; --- The rxBuffer --- ; Multi-Purpose RAM space ; For Roll Left/Right ; rxBuffer:0 = Row Counter ; rxBuffer:1 = Column Counter ; rxBuffer=4 = Frame1 Input Data ; rxBuffer=6 = Frame0 Input Data ; For Roll Up/Down ; rxBuffer[0..5] = Incoming Data rxBuffer:0 row_count:1 column_count:1 bitShifter:1 voldemort:1 ; The BYTE that shall not be named input1:1 input2:0 ; Maps onto rxBufferEnd rxBufferEnd:1 ; Point to last BYTE of rxBuffer ; MemCopy memcpy_i memcpy_a memcpy_b end_global_vars:0 ENDC if end_global_vars > 0x80 error "Global Variable Space overrun" endif ; ----------------------------------- ; Macro's to help with BANK selection ; ----------------------------------- #define BANK0 bcf STATUS,RP0 #define BANK1 bsf STATUS,RP0 FRAMESIZE EQU d'96' HALFFRAMESIZE EQU d'48' ; ----------------------------------- ; Global Status Bits (gSTATUS) ; ----------------------------------- g_SHOW EQU d'0' g_ESCAPE EQU d'1' g_STANDALONE EQU d'2' g_DEBUG EQU d'7' ; --------------------------------- ; Triks-C commands ; 0b 1CCCCxxx - C=Channel x = CMD ; --------------------------------- ; Trik-c backwards compatability ; ; Cmd_DISP_OFF EQU h'00' ; Cmd_ROLL_L EQU h'01' ; Cmd_ROLL_R EQU h'02' ; Cmd_ROLL_U EQU h'03' ; Cmd_ROLL_D EQU h'04' ; Cmd_FRAME EQU h'05' ; Cmd_CLR_FRAME EQU h'06' ; Cmd_DISP_ON EQU h'07' ; ; --------------------------------- ; Pik-C commands ; 0b 0CCCCxxx - C=Channel, x=CMD ; --------------------------------- ; (payload size in brackets) ; PIKC_CONFIG - program the device address (1) ; FRAME_SELECT - read the frame from the EEPROM (1) ; FRAME_EE_WRITE0 - write the frame to the EEPROM (0) ; FRAME_EE_WRITE1 - write the frame to the EEPROM (0) ; STAND_ALONE - begin running "Stand alone" (0) ; ; Cmd_CONFIG EQU h'00' ; Cmd_FRAME_SELECT EQU h'01' ; Cmd_FRAME_EE_WRITE0 EQU h'02' ; Cmd_FRAME_EE_WRITE1 EQU h'03' ; Cmd_STAND_ALONE EQU h'04' ; ------------------------------------ ; Constant Definitions to map function ; to the associated PORT. ; ------------------------------------ #define mDATA0 PORTC,0 ; DATA0 #define mDATA1 PORTC,1 ; DATA1 #define mDATA2 PORTC,2 ; DATA2 #define mDATA3 PORTC,3 ; DATA3 #define mSTROBE PORTA,2 ; DATA_STROBE #define mINIT PORTA,4 ; INIT #define mSTATUS_LED PORTA,5 ; STATUS LED for development ; ------------------------------------ ; Memory map of the EEPROM ; ------------------------------------ EE_PIKC_FRAME0 EQU D'0' EE_PIKC_FRAME1 EQU D'160' EE_PIKC_ADDR EQU D'96' ; ------------------------------------ ; Constant Definitions SERIAL PROTOCOL ; ------------------------------------ RX_SYNC EQU h'7E' RX_PAD EQU h'7D' RX_ESC EQU h'7F' ; ------------------------------------ ; MACRO Definitions ; ------------------------------------ chgState macro newState movlw newState movwf smSTATE endm ;branch not equal bne MACRO fr1,fr2,address movf fr2,W subwf fr1,W btfss STATUS,Z goto address endm bnel MACRO fr1,literal,address movf fr1,W sublw literal btfss STATUS,Z goto address endm ;branch if equal beq MACRO fr1,fr2,address movf fr2,W subwf fr1,W btfsc STATUS,Z goto address endm beql MACRO fr1,literal,address movf fr1,W sublw literal btfsc STATUS,Z goto address endm dbg MACRO fr1 ;--------- Start f DEBUG btfss gSTATUS, g_DEBUG goto blinkend movf fr1,w andlw h'07' movwf dumpChar ;swapf temp,f blinkloop call BlinkStatus decfsz dumpChar,f goto blinkloop blinkend call loop endm ;--------- End of DEBUG ; ---------------------------------------------- ; Start of the "CODE" section ; ---------------------------------------------- ORG 0x000 ; Main Program clrf PCLATH goto start ORG 0x004 ; Interrupt handler goes here intHandler movwf wsave ; Store the usual bits when interrupting swapf STATUS, w clrf STATUS movwf ssave movf PCLATH, w movwf psave ; movf FSR,w ; Also store the FSR ; movwf fsrsave ; ToDo - Actually output the DATA ; ------- Actual Interrupt Routine Here -------------------- movlw D'223' ; TMR0 will roll over every 40.0 uS movwf TMR0 ; btfss gSTATUS, g_SHOW ; Is "Output" enabled? goto intHandlerExit nop ; ------- Actual Interrupt Routine Ends -------------------- intHandlerExit BCF INTCON,T0IF ; Clear the TMR0 interrupt flag ; movf fsrsave,w ; Re-Store the FSR ; movwf FSR ; movf psave,w ; Restore whatever was happening prior movwf PCLATH ; to the interrupt and get back to swapf ssave,w ; gathering DMX data. movwf STATUS swapf wsave,f swapf wsave,w retfie ; Back to gathering DMX data ; ----------------------------------------------------------------------------- ; ----------------------- Main Program Starts Here ---------------------------- ; ----------------------------------------------------------------------------- start: call pikcInit ; Initialize pins, oscillator, etc ; --------------- ; Serial Rx Loop ; --------------- mLoop btfss PIR1,RCIF ; Has a Byte arrived? goto mLoop_Czeck_Standalone movf RCREG,W ; Then, capture & move to 'w'... movwf rxBYTE ; Store the BYTE for comparison movlw d'6' ; Rx error mask (framing error, overrun error) andwf RCSTA,w ; get (masked) rx status btfss STATUS,Z goto rxError ; goto error routine beql rxBYTE,RX_PAD,mLoop ; Ignore PAD bytes movf rxBYTE,W ; Echo the character to the serial port movwf TXREG btfsc gSTATUS,g_ESCAPE ; Is there an Escape pending? goto rxEscapeData beql rxBYTE,RX_ESC,rxEscape ; Is this an Escape character? movf smSTATE,W ; Jump to STATE, and let it handle the rxBYTE movwf PCL rxEscape bsf gSTATUS, g_ESCAPE ; Record that we have an ESCAPE pending goto mLoop rxEscapeData bcf gSTATUS, g_ESCAPE ; Stop waiting on the ESCAPE encoded byte movf rxBYTE, w ; Calculate the "Escape Encoded" value addlw h'4E' ; Maps 2F::7D, 30::7E, 31::7F movwf rxBYTE ; Place the results in the BYTE movf smSTATE,W ; Jump to STATE, and let it handle the rxBYTE movwf PCL mLoop_Czeck_Standalone ; ToDo - add a form of Watchdog. ; If we don't see any Serial traffic, go into Standalone handling goto mLoop rxError: ;call BlinkStatus bcf RCSTA,CREN bsf RCSTA,CREN chgState smWait4Sync ; Wait for the SYNC byte goto mLoop ; -------------- ; End of Rx Loop ; ------------------------------------------------------- ; From here down the "state machine" states to handle the ; commands from the PC ; ------------------------------------------------------- smWait4Sync bnel rxBYTE,RX_SYNC,mLoop ; Wait for a SYNC otherwise loop chgState smWait4Cmd goto mLoop ; Continue waiting smWait4Cmd beql rxBYTE,RX_SYNC,mLoop ; IF was a SYNC - stay in this state movf rxBYTE,w ; Was this addressed to me? andwf pikcADDR,w ; Compare against saved address btfss STATUS,Z ; If zero bits match go back to waiting goto w4CmdParse ; Jump to the Command interpreter chgState smWait4Sync ; or go Back to waiting for SYNC goto mLoop w4CmdParse btfsc rxBYTE,7 ; Test for TRICK-C vs PIK-C goto w4CmdTrikC ; High order BIT w4CmdPikC movf rxBYTE,w ; Mask out the COMMAND bits andlw h'03' movwf cmdPENDING addwf PCL,F ; Use the JUMP table to jump to the appropriate handler goto setupSetAddr ; cmd=0 PIK-C setAddress goto setupFrameRead ; cmd=1 Payload = BYTE indicating which frame 0,1 = EEPROM goto cmdFrameWrite1 ; cmd=2 Write to EEPROM FRAME 1 goto cmdFrameWrite0 ; cmd=3 Write to EEPROM FRAME 0 goto cmdStandAlone ; cmd=4 Invoke stand alone mode nop ; cmd=5 These are all error conditions, as we only have nop ; cmd=6 four additional PIK-C commands at this time. nop ; cmd=7 chgState smWait4Sync goto mLoop w4CmdTrikC movf rxBYTE,w ; Mask out the COMMAND bits andlw h'07' movwf cmdPENDING addwf PCL,F ; Use the JUMP table to goto the appropriate handler w4Cmdtable goto cmdFrameWrite1 ; DEBUG ONLY cmdBlank ; cmd=0 Trik-C Blank (turn Off) goto setupVertical ; cmd=1 Trik-C Roll Left goto setupVertical ; cmd=2 Trik-C Roll Right goto setupHorizontal ; cmd=3 Trik-C Roll Up goto setupHorizontal ; cmd=4 Trik-C Roll Down goto setupFrame ; cmd=5 Trik-C Full Frame goto cmdLeft ; DEBUG ONLY cmdClear ; cmd=6 Trik-C Clear image goto cmdRight ; DEBUG ONLY cmdShow ; cmd=7 Trik-C Show (turn On) smWait4Packet ; Copy data into packet until full ; Note "filling in reverse order" ; why? because that's how the PC sends it. (TriksC Protocol) movf rxBYTE,w movwf INDF decf FSR,F decfsz payloadCount,F goto mLoop movf cmdPENDING,W ; Use the cmdPending as an offset to the jump table addwf PCL,F ; Use the JUMP table to jump to the appropriate handler w4packetTable goto cmdSetAddr ; cmd=0 pikC command (doubling atop "BLANK") goto cmdLeft ; cmd=1 goto cmdRight ; cmd=2 goto cmdUp ; cmd=3 goto cmdDown ; cmd=4 goto cmdFrame0 ; cmd=5 goto cmdFrame1 ; cmd=6 pikC command doubling atop "Clear" goto cmdFrameRead ; cmd=7 pikC command doubling atop "Show" ; ----------- Command Handlers ----------------------- cmdBlank bcf gSTATUS,g_SHOW ; Clear the SHOW bit in the gSTATUS register ;ToDo - pull the INHIBIT pin on PORTC HIGH goto doneCmd cmdShow bsf gSTATUS,g_SHOW ; Set the SHOW bit in the gSTATUS register ;ToDo - clear the INHIBIT pin on PORTC goto doneCmd cmdClear bsf gSTATUS,g_SHOW ; LABRAT - needs to re-write this. What will it do? ;ToDo - pull the INHIBIT pin on PORTC HIGH goto doneCmd setupFrame movlw HALFFRAMESIZE ; Numer of bytes in the payload (1st 1/2 a frame) movwf payloadCount BANKISEL Fr1Row0 movlw Fr1End ; Point to last BYTE of BANK1 Buffer movwf FSR ; as the data arrives in that order decf FSR,F goto doneSetup setupVertical movlw d'2' ; Numer of bytes in the payload movwf payloadCount movlw rxBufferEnd ; Point to the RxBufferEnd movwf FSR goto doneSetup setupHorizontal movlw d'6' ; Numer of bytes in the payload movwf payloadCount movlw rxBufferEnd ; Point to the RxBufferEnd movwf FSR goto doneSetup cmdRight BANKISEL Fr0Row0 movlw Fr0Row0 movwf FSR ; Point in the BANK movf input2,W ; Get the appropriate byte from the payload movwf bitShifter ; Everything is where we want it. clrf voldemort ; Indicate 1st time throught this loop cmr_forEachBank movlw d'8' ; 8 rows per frame movwf row_count ; cmr_forEachRow movlw d'6' ; 6 bytes per row movwf column_count ; rlf bitShifter,F ; Put the "next" highest bit into 'C' cmr_forEachColumn rlf INDF,F ; Rotate the payload NOTE: inverse rotate due to msb output ordering incf FSR,F ; Increment to the next BYTE in the stream decfsz column_count ; Count down all 6 bytes in the ROW goto cmr_forEachColumn decfsz row_count goto cmr_forEachRow btfsc voldemort,1 ; Was this the second frame? goto doneCmd ; Yes - we are done BANKISEL Fr1Row0 movlw Fr1Row0 movwf FSR movf input1,W movwf bitShifter bsf voldemort,1 ; Flag that we are executing the SECOND 1/2 of the shiftloop goto cmr_forEachBank cmdLeft BANKISEL Fr0Row0 call BlinkStatus ; Black Magic - makes it work...(ugh) movlw Fr0End movwf FSR ; Point in the BANK movf input2,W ; Get the appropriate byte from the payload movwf bitShifter ; Everything is where we want it. clrf voldemort ; Indicate 1st time throught this loop cml_forEachBank movlw d'8' ; 8 rows per frame movwf row_count ; cml_forEachRow movlw d'6' ; 6 bytes per row movwf column_count ; rrf bitShifter,F ; Put the "next" lowest bit into 'C' cml_forEachColumn decf FSR,F ; Decrement to the next BYTE in the stream rrf INDF,F ; Rotate the payload NOTE: inverse rotate due to msb output ordering decfsz column_count ; Count down all 6 bytes in the ROW goto cml_forEachColumn decfsz row_count goto cml_forEachRow btfsc voldemort,1 ; Was this the second frame? goto doneCmd ; Yes - we are done BANKISEL Fr1Row0 movlw Fr1End movwf FSR movf input1,W movwf bitShifter bsf voldemort,1 ; Flag that we are executing the SECOND 1/2 of the shiftloop goto cml_forEachBank cmdUp ; Shif the Top 7 lines of the Bank 0 frame ; Copy 1 line from Top of Bank 1 frame ; Ship the Top 7 lines of the Bank 1 frame movlw Fr0Row0 movwf memcpy_b movlw Fr0Row1 movwf memcpy_a movlw d'42' movwf memcpy_i BANKISEL Fr0Row0 call memCpyUp ; Copy the 6 bytes from Bank1 to Bank 0 movlw Fr0Row7 movwf memcpy_b movlw Fr1Row0 movwf memcpy_a movlw d'6' movwf memcpy_i call memCpyUpBanks ; Copy from Bank 1 to Bank 0 movlw Fr1Row0 movwf memcpy_b movlw Fr1Row1 movwf memcpy_a movlw d'42' movwf memcpy_i BANKISEL Fr1Row0 call memCpyUp movlw Fr1Row7 movwf memcpy_b movlw rxBuffer movwf memcpy_a movlw d'6' movwf memcpy_i BANKISEL Fr1Row0 call memCpyUp goto doneCmd cmdDown ; Shif the Bottom 7 lines of the Bank 1 frame ; Copy 1 line from Bottom of Bank 0 frame ; Ship the Bottom 7 lines of the Bank 0 frame movlw Fr1End movwf memcpy_b movlw Fr1Row7 movwf memcpy_a movlw d'42' movwf memcpy_i BANKISEL Fr1Row0 call memCpyDown ; Copy the 6 bytes from Bank1 to Bank 0 movlw Fr1Row1 movwf memcpy_b movlw Fr0End movwf memcpy_a movlw d'6' movwf memcpy_i call memCpyDownBanks ; Copy from Bank 1 to Bank 0 movlw Fr0End movwf memcpy_b movlw Fr0Row7 movwf memcpy_a movlw d'42' movwf memcpy_i BANKISEL Fr1Row0 call memCpyDown movlw Fr0Row0 movwf memcpy_b movlw rxBuffer movwf memcpy_a movlw d'6' movwf memcpy_i BANKISEL Fr0Row0 call memCpyUp ; Can use Use Forward copy now goto doneCmd cmdFrame1 ; BANK0 Copy of Frame is completed ; NOTE - we don't change the primary state, we will continue to receive data. ; instead we change the command pending, to be Frame1 movlw d'6' ; Update the cmdPENDING to be the BANK1 data movwf cmdPENDING ; movlw HALFFRAMESIZE ; Another 48 bytes expected movwf payloadCount BANKISEL Fr0Row0 movlw Fr0End ; Point to the last byte of the BANK1 Buffer movwf FSR ; because the data arrives in this order decf FSR,F goto mLoop ; Stay in w4Packet state (for second half of FRAME) cmdFrame0 ; BANK1 copy of frame is completed - just exit clean. ; These are not the droids you want... move along. goto doneCmd ; - - - - - - - - - - - ------------- - - - - - - - - - - - - ; - - - - - - - - - - - PikC commands - - - - - - - - - - - - ; - - - - - - - - - - - ------------- - - - - - - - - - - - - ; ------------- ; cmdStandAlone - invoke the standAlone functionality ; Payload = none ; ------------- cmdStandAlone bsf gSTATUS,g_STANDALONE goto doneCmd ; ------------- ; cmdFrameRead - Read a frame from ROM or EEPROM ; Payload = 1 ; FrameId - <0,1> = EEPROM Frame 0 or 1, and <2..9> = ROM Frame 0..8 ; ------------- setupFrameRead movlw h'07' ; Update the cmdPENDING to be a 'FRAME READ' command movwf cmdPENDING ; movlw d'1' ; Numer of bytes in the payload movwf payloadCount movlw rxBufferEnd ; Point to the RxBufferEnd movwf FSR goto doneSetup cmdFrameRead ; ToDo - ; Use payload byte to select image to read 0/1 = EEPROM ; 2..N = ROM images goto doneCmd ; ------------- ; cmdFrameWrite0 - Copy existing RAM image to EEPROM Frame 0 location ; cmdFrameWrite1 - Copy existing RAM image to EEPROM Frame 1 location ; Payload = none ; ------------- cmdFrameWrite0 BANKSEL EEADR ; Set target to eepromFrame0 movlw EE_PIKC_FRAME0 ; Frame 0 Start Address movwf EEADR ; Data Memory Address to write goto frameWrite cmdFrameWrite1 BANKSEL EEADR ; Set target to eepromFrame1 movlw EE_PIKC_FRAME1 ; Frame 1 Start Address movwf EEADR ; Data Memory Address to write frameWrite ; Copy RAM frame to the EEPROM address BANKSEL PIR1 bcf PIR1,EEIF ; clear the EEIF interupt bit BANKSEL EEDAT bcf EECON1, EEPGD ; Point to DATA memory bsf EECON1, WREN ; Enable writes BANKISEL Fr0Row0 movlw Fr0Row0 ; Start Address of RAM copy movwf FSR call eeFrameWrite ; Clock data out to EEPROM BANKISEL Fr1Row0 movlw Fr1Row0 ; Start Address of RAM copy movwf FSR call eeFrameWrite ; Clock data out to EEPROM BANKSEL EECON1 bcf EECON1, WREN ; Disable writes to EEPROM call BlinkStatus goto doneCmd ; ------------- ; cmdSetAddr - Program the device ADDRESS ; Payload = 1
NOTE: ADDRESS IN BITS 4..7 (NOT SHIFTED RIGHT) ; ------------- setupSetAddr movlw d'1' ; Numer of bytes in the payload movwf payloadCount movlw rxBufferEnd ; Point to the RxBufferEnd movwf FSR goto doneSetup cmdSetAddr ; Copy to pikcADDR movf rxBYTE,W movlw pikcADDR call eeWriteAddr ; Write into EE goto doneCmd ; Generic "exit" routines doneSetup chgState smWait4Packet ; goto mLoop doneCmd BANKSEL Fr0Row0 chgState smWait4Sync ; goto mLoop ; ----------- Routines for Starting the Chip --------- pikcInit BANKSEL OSCCON movlw 0x71 ; 8 MHz internal oscillator movwf OSCCON Wait4Clock2Settle btfss OSCCON,HTS goto Wait4Clock2Settle clrf OSCTUNE BANKSEL PORTA ; Memory bank 0 clrf PORTA ; All PORTA Pins off movlw 0x07 movwf CMCON0 ; disable the comparators bcf WDTCON,0 ; turn off WDT bcf ADCON0,0 ; turn off AD Convert clrf PORTC ; All PORTC Pins off BANKSEL ANSEL ; Switch to memory bank 1 clrf ANSEL ; Turn off A/D Converters ; setup porta & portc bcf TRISC,0 ; DATA0 bcf TRISC,1 ; DATA1 bcf TRISC,2 ; DATA2 bcf TRISC,3 ; DATA3 bcf TRISA,2 ; DATA_STROBE bcf TRISA,4 ; INIT bcf TRISA,5 ; STATUS_LED BANKSEL PORTA ; Memory bank 0 call meminit ;call timerinit ; Initialize TIMER0 and enable TMRO interrupts call rxinit ; Set up the EUSART to receive DMX at 250,000 baud return ; ----------- Memory Initalization --------- meminit chgState smWait4Sync ; Default to w4SYNC state call eeReadAddr BANKSEL pikcADDR movlw h'78' ; Default address to 0x18 for debugging purposes movwf pikcADDR call BlinkStatus BANKSEL EEADR movlw high Frame00 movwf EEADRH movlw low Frame00 movwf EEADR bsf EECON1, EEPGD ; Reading from ROM (not eeprom) BANKSEL Fr0Row0 ; Setup to fill BANK0 (TOP) Buffer movlw Fr0Row0 ; Store target into FSR for INDF use movwf FSR ; call flashCpy BANKSEL Fr1Row0 ; Setup to fill BANK1 (BOTTOM) Buffer movlw Fr1Row0 ; Store target into FSR for INDF use movwf FSR call flashCpy return ; ----------- Serial Routines --------- rxinit BANKSEL PORTC bsf PORTC,5 ; PORTC.5 is input for EUSART clrf SPBRGH ; 8 = 57.6, 25 = 19.2 movlw d'8' movwf SPBRG clrf BAUDCTL bsf BAUDCTL,BRG16 ; receiving serial at 57.6k bits per second movlw 0x20 ; Initialize the TXSTA movwf TXSTA ; movlw 0x90 ; Serial Port and continuous receive enabled movwf RCSTA return ; ----------- timerinit --------- timerinit movlw B'10100000' ; Enable global and TMR0 interrupts movwf INTCON BANK1 clrf OPTION_REG ; No prescaler for TMR0 needed BANK0 return ; ----------------- eeReadAddr ------- eeReadAddr ; read the dmx address from the eeprom ; dmxhighbyte from eeprom addr 00 ; dmxlowbyte from eeprom 01 ; first read the dmxhighbyte BANKSEL EEADR movlw EE_PIKC_ADDR ; eeprom addr movwf EEADR ; data address to read bcf EECON1, EEPGD ; point to adata memory bsf EECON1, RD ; EE read movf EEDAT, w ; w = eeprom data. BANKSEL pikcADDR movwf pikcADDR ; now in dmxhighbyte mem location return ; ----------------- eeWriteAddr ------- eeWriteAddr BANKSEL PIR1 bcf PIR1,EEIF ; clear the EEIF interupt bit BANKSEL EEADR movlw EE_PIKC_ADDR ;PIKC HIGH ADDRESS movwf EEADR ;Data Memory Address to write BANKSEL pikcADDR movf pikcADDR,w ; BANKSEL EEDAT movwf EEDAT ;Data Memory Value to write bcf EECON1, EEPGD ;Point to DATA memory bsf EECON1, WREN ;Enable writes bcf INTCON, GIE ;Disable INTs. btfsc INTCON, GIE ;SEE AN576 goto $-2 movlw 0x55 ; movwf EECON2 ;Write 55h movlw 0xAA ; movwf EECON2 ;Write AAh bsf EECON1, WR ;Set WR bit to begin write BANKSEL PIR1 btfss PIR1,EEIF ; need to keep checking for EEIF being set (write complete.) goto $-2 bcf PIR1,EEIF ; clear the EEIF write complete interupt BANKSEL EECON1 bcf EECON1, WREN ;Disable writes return ; ----------------- eeFrameWrite --------------- eeFrameWrite movlw HALFFRAMESIZE movwf temp ; Number of bytest to copy eeFrameWriteLoop movf INDF,W BANKSEL EEDAT movwf EEDAT ;Data Memory Value to write bcf INTCON, GIE ;Disable INTs. btfsc INTCON, GIE ;SEE AN576 goto $-2 movlw 0x55 ; movwf EECON2 ;Write 55h movlw 0xAA ; movwf EECON2 ;Write AAh bsf EECON1, WR ;Set WR bit to begin write BANKSEL PIR1 btfss PIR1,EEIF ; need to keep checking for EEIF being set (write complete.) goto $-2 bcf PIR1,EEIF ; clear the EEIF write complete interupt incf FSR,f ; Point at the next byte BANKSEL EEADR incf EEADR,f decfsz temp,f goto eeFrameWriteLoop return ; ------------------ flashCopy ---------------- ; Copies a 48 byte 1/2 frame from ROM or EEPROM flashCpy movlw HALFFRAMESIZE movwf temp ; Going to copy 48 bytes BANKSEL EEADR flashCpyLoop bsf EECON1, RD NOP ; Required for ROM reads, and won't hurt NOP ; for EEPROM reads either... movf EEDAT,W movwf INDF incf FSR,f incf EEADR,f decfsz temp,f goto flashCpyLoop return ;===================================PIC16CXXX=================================== ; memcpy_a ; src pointer base ; memcpy_b ; dst pointer base ; memcpy_i ; byte count held in reg file ; USES: ; memcpy_temp ; temp data storage memCpyUp movf memcpy_a,W movwf FSR movfw INDF movwf temp incf memcpy_a,f movf memcpy_b,W movwf FSR movf temp,W movwf INDF incf memcpy_b,f decfsz memcpy_i, F goto memCpyUp return memCpyUpBanks BANKISEL Fr0Row0 movf memcpy_a,W movwf FSR movfw INDF movwf temp incf memcpy_a,f BANKISEL Fr1Row1 movf memcpy_b,W movwf FSR movf temp,W movwf INDF incf memcpy_b,f decfsz memcpy_i, F goto memCpyUpBanks return memCpyDown decf memcpy_a,W movwf memcpy_a movwf FSR movfw INDF movwf temp decf memcpy_b,W movwf memcpy_b movwf FSR movf temp,W movwf INDF decfsz memcpy_i, F goto memCpyDown return memCpyDownBanks BANKISEL Fr1Row0 decf memcpy_a,W movwf memcpy_a movwf FSR movfw INDF movwf temp BANKISEL Fr0Row1 decf memcpy_b,W movwf memcpy_b movwf FSR movf temp,W movwf INDF decfsz memcpy_i, F goto memCpyDownBanks return ;---------- ; rev_nibble ; reverse order of BITS in the niblle ; *fastest method = lookup table revNibble andlw h'0F' addwf PCL,F retlw h'00' ;0000 -> 0000 retlw h'08' ;0001 -> 1000 retlw h'04' ;0010 -> 0100 retlw h'0C' ;0011 -> 1100 retlw h'02' ;0100 -> 0010 retlw h'0B' ;0101 -> 1010 retlw h'06' ;0110 -> 0110 retlw h'0E' ;0111 -> 1110 retlw h'01' ;1000 -> 0001 retlw h'09' ;1001 -> 1001 retlw h'05' ;1010 -> 0101 retlw h'0D' ;1011 -> 1101 retlw h'03' ;1100 -> 0011 retlw h'0B' ;1101 -> 1011 retlw h'07' ;1110 -> 0111 retlw h'0F' ;1111 -> 1111 ;---------- BlinkStatus BANKSEL PORTC bsf mSTATUS_LED ; Turn on Status call loop call loop bcf mSTATUS_LED call loop call loop return ; ----------- loop1sec ------------ loop1sec call loop call loop call loop call loop return ; ----------- 250ms delay --------- loop movlw d'250' ; 250mS call WaitNms ; return ; ----------------- WaitNms -------- WaitNms movfw timer ; timer_local=W loopNms movlw d'248' ; revised value due to extras call Wait1ms ; goto $+1 ; 2 clock cycles decfsz timer,f ; Dec loop variable and check goto loopNms ; No, keep looping return ; Yes, Nms done ; ----------------- 1 ms delay ------- Wait1ms movlw d'255' ; Initial value - tweak if req. movwf COUNT loop1ms decfsz COUNT,1 goto loop1ms ; No, keep looping return ; Yes, 1ms done ;******************************************************************************* ; Frame table (lookup) ; This is where the 8 Frames + init frame are stored for stand alone mode ;******************************************************************************* ORG 0xC00 ; Data Tables Frame00: dt .255, .255, .255, .255, .255, .255 dt .1 , .0 , .0 , .0 , .0 , .128 dt .249, .30 , .39 , .243, .0 , .143 dt .33 , .34 , .34 , .9 , .128, .128 dt .33 , .34 , .226, .8 , .128, .128 dt .33 , .30 , .98 , .112, .156, .128 dt .33 , .6 , .226, .128, .128, .128 dt .33 , .10 , .34 , .129, .128, .128 dt .33 , .50 , .39 , .123, .0 , .143 dt .1 , .0 , .0 , .0 , .0 , .128 dt .1 , .0 , .0 , .0 , .224, .184 dt .1 , .0 , .0 , .0 , .160, .160 dt .1 , .0 , .0 , .0 , .160, .186 dt .1 , .0 , .0 , .0 , .160, .136 dt .1 , .0 , .0 , .0 , .224, .184 dt .255, .255, .255, .255, .15 , .128 Frame01: dt .255 , .255 , .1 , .0 , .255 , .255 dt .255 , .255 , .2 , .0 , .255 , .255 dt .255 , .255 , .4 , .0 , .255 , .255 dt .255 , .255 , .8 , .0 , .255 , .255 dt .255 , .255 , .16 , .0 , .255 , .255 dt .255 , .255 , .32 , .0 , .255 , .255 dt .255 , .255 , .64 , .0 , .255 , .255 dt .255 , .255 , .128, .0 , .255 , .255 dt .255 , .255 , .0 , .1 , .255 , .255 dt .255 , .255 , .0 , .2 , .255 , .255 dt .255 , .255 , .0 , .4 , .255 , .255 dt .255 , .255 , .0 , .8 , .255 , .255 dt .255 , .255 , .0 , .16 , .255 , .255 dt .255 , .255 , .0 , .32 , .255 , .255 dt .255 , .255 , .0 , .64 , .255 , .255 dt .255 , .255 , .0 , .128, .255 , .255 ORG 0xD00 ; Data Tables Frame02: dt .255 , .255 , .1 , .0 , .255 , .255 dt .255 , .255 , .2 , .0 , .255 , .255 dt .255 , .255 , .4 , .0 , .255 , .255 dt .255 , .255 , .8 , .0 , .255 , .255 dt .255 , .255 , .16 , .0 , .255 , .255 dt .255 , .255 , .32 , .0 , .255 , .255 dt .255 , .255 , .64 , .0 , .255 , .255 dt .255 , .255 , .128, .0 , .255 , .255 dt .255 , .255 , .0 , .1 , .255 , .255 dt .255 , .255 , .0 , .2 , .255 , .255 dt .255 , .255 , .0 , .4 , .255 , .255 dt .255 , .255 , .0 , .8 , .255 , .255 dt .255 , .255 , .0 , .16 , .255 , .255 dt .255 , .255 , .0 , .32 , .255 , .255 dt .255 , .255 , .0 , .64 , .255 , .255 dt .255 , .255 , .0 , .128, .255 , .255 Frame03: dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 ORG 0xE00 ; Data Tables Frame04: dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 Frame05: dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 ORG 0xF00 ; Data Tables Frame06: dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 Frame07: dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 dt 0 , 0 , 0 , 0 , 0 , 0 EndofData: dt "(c) 2009 Andrew Williams" ; ----------------- end! ------- END