; ---------------------------------------------------------------------------- ; ; Program LOGAN.18ASM ; Author Wim de Vree, pe1grl@amsat.org ; ; 4- or 8-channel Digital Signal Logger for a PIC microprocesser ; Samples a digital signal and sends it's characteristics over ; a serial link to a PC. ; ; As of March 2009: An 8 channel serial monitor option is added. ; Supported Baudrates are from 300 upt to 19200 Baud ; Currently only 7bit data can be monitored (although the ; UART is setup as 8bits, no parity) ; ; As of June 2009: Optional Memory Compression added in 2/5/10u fast ; 2, 4 and 8 bit sampling modes. This can allow much longer traces ; (depending on the activity on the lines) ; ; Revision history ; -------------------- VERSION CHANGED TO 6 -------------------- ; 2009-06-17 Added search for datatrigger in transitional sampling mode ; Enlarged the part of the buffer where the trigger is searched ; (used to be first 50%, now 80%) ; 2009-06-16 Added 4bit Transitional sampling (compression max 16X) and ; 2bit Transitional sampling (compression max 64X) ; Fixed a minor bug when the clock rolled over and the ; data changed at exactly the same moment in the FAST ; transitional 5u and 10u mode. ; Rewritten to allow the user to select which type of ; sampling (timed/transitional) to use. ; 2009-06-15 Added a Hold-off delay to the FAST starttrigger ; units is microseconds, range 0..65535 ; 2009-06-14 Added "Transition sampling" for FAST mode which samples ; up to 3420 changes (18F2525) or 768 changes (18F252) in ; 2usec or slower modes. This extends the maximum sample time ; up to 256X depending on the compression (nr. of.data changes) ; This mode is supported for 2, 5 and 10 usec sample rates ; For now only used in 8 bit mode (but same code could be used ; for 2 and 4 bit although there is no buffer gain ; 2009-03-25 -------------------- VERSION CHANGED TO 5 -------------------- ; Added 5 and 10 usec sampling options in FAST mode. ; Added experimental code for 2bit normal mode (incomplete) ; 2009-03-24 Redefined the command set for fast sampling. ; First select the mode, then issue the start command ; Allows more widths/rates to be added ; Also: Timing bug fixed in 4bit 2us fast sampling ; 2009-03-23 Memory layout changed to support 3840 bytes of sample ; storage on an 18F2525 (was 3584) ; Added 2bit fast sampling core for 1usec and 2usec ; sampling. Trigger searching not yet implemented ; 2009-03-22 Completed & Tested the starttrigger option ; 2009-03-18 Rewritten to allow edge-selection on the external ; trigger input. ; 2009-03-14 BUG FIX: 4bit sampling at 20usec never worked before ; due to a protocol error. ; 2009-03-12 Finalised & Tested this software version. ; 2009-03-09 Added a START-TRIGGER option to trace one-time events ; in FAST mode. The L.A. loops until a match is found ; on the datalines before is starts capturing. If a ; MASK of 0x00 is specified the external "Trigger Line" ; (PortC,3) is monitored. A Trigger is a HIGH condition ; on the dataline. The Duration of the "high" condition ; should be at least 1uSec. There is a delay of up to ; 2 microseconds before the actual capturing starts. ; The actual delay depends on the FAST mode which is ; selected. ; 2009-03-08 Completed porting of 16F code, new commands added to ; set mask and baudrate for capture device. ; Some cleanup and minor improvements of old code. ; 2009-03-06 -------------------- VERSION CHANGED TO 4 -------------------- ; Added Serial port monitoring (command 'S'). ; The serial port monitor uses the HIGH priority int. ; The logic analyser uses the LOW priority int. ; This saves testing in the ISR (which should be as short ; as possible). Because only one of the modes is active ; at any given time, we can use FAST interrupt returns ; in both modes. ; Up to 8 Serial ports can be monitored up to 19K2 Baud ; Currently the monitoring baudrate is fixed at 4800 Baud ; 2006-06-04 Initial experiments with a FAST 2 BIT mode ; (longer traces for e.g. I2C monitoring) ; 2005-10-16 Bug fixed in 4bit Fast Trigger search. ; Changed the version info block ; The first number indicates the processor, the second ; the version. So the versions are now [2,3] for an 18F252 ; and [3,3] for an 18F2525 ; 2005-05-10 Fixed problem with 500nsec 4 bit sampling on the 18F2525 ; by using two loops. ; VERSION INFO changed to [2,8] for the 18F252 ; VERSION INFO changed to [3,1] for the 18F2525 ; 2005-05-09 Changed fast data protocol to support the PIC18F2525 ; uses conditional assembly for this ; Fast buffer size on an 18F252 : 1280 bytes ( 5 banks) ; Fast buffer size on an 18F2525: 3684 bytes (14 banks) ; 2005-02-28 Removed experimental & 48 MHz code ; 100 usec sampling is now 20 usec sampling ; On interrupt buffer full, flush the buffer before ; the abort char is send ; 2005-02-24 POST-Triggering added in FAST sampling ; (The data is scanned for the triggerpattern, and if not found ; a new scan is started until the pattern is found) ; VERSION INFO changed to [2,7] ; 2005-02-16 Added 4bit 500ns FAST Sampling ; Inlined SendChar for a little performance improvement ; VERSION INFO changed to [2,6] ; 2005-02-15 FAST sampling: Buffer size increased from 1024 to 1280 bytes ; Experimental 2bit mode added (only 1 and 2 usec rates) (6400 samples) ; Added 4bit 2us FAST Sampling (was omitted) ; Interrupt handler and DOSAMPLE loop optimized ; VERSION INFO changed to [2,5] ; 2005-02-14 Modifications to high speed sampling mode: ; - 10 usec sampling replaced with a 2 usec sampling. ; - in 1 and 2 usec sampling the user can select 4 or 8 bit ; sampling (Now 2048 samples kan be stored) ; VERSION INFO changed to [2,4] ; 2005-02-09 Added "FAST sampling modes for 100nsec, 500nsec, 1usec ; and 10 usec. Does not work in continous mode but a sample, ; transmit method (So the max sampling time is limited to the ; RAM buffer which is 1024 bytes. ; VERSION INFO changed to [2,3] ; 2004-05-11 Hardware lines changed: ; LED is connected to GND, not +5V ; Speed Select moved to RC4 ; 2004-05-01 Added 12 MHz xtal support which will support a 1 Megabit ; transfer rate ; VERSION INFO changed to [2,2] ; 2004-04-21 BaudRate select added via RC3, low=115K, high=500K ; 1 line Hardware Handshake added (sense rempote RTS line) ; Fixed bug with activity led (always ON during sampling) ; Fixed doc: PB7&PB6 doc was incorrect ; 2004-04-14 Some code cleanup and comments added ; VERSION INFO changed to [2,1] (18F252 processor, version1) ; 2004-04-13 Killed 500 uSec sampling, ; Redefined opcodes (0-1-2-3) ; Added 8-bit sampling options (4-5-6-7) ; Added Get Version command ('?') ; 2004-04-05 Got the 18F252 version working ; added 2, 5 and 500 usec sampling, chars are now 1-5 for 2-500 ; usec timebase. Overrun handling changed: do not hang the uproc ; but stop sampling. ; 2004-04-04 Ported to 18F252 ; Advantages: ; - More sample lines are available (8) ; - Faster samplin rate (higher clock, better architecture) ; - Larger ring buffer (1.5K Ram vs 384 bytes) ; 2004-03-10 Support 10 and 100 usec sampling times ; 2004-03-06 Max sampling rate is 10 uSec as the worst case int. loop ; takes some 8 microseconds. Sampling rate is fixed for now. ; 2004-03-01 Rewritten from a edge-triggered (PortB change interrupt to ; sampling scope (TMR based). Allows "slow" implementations ; (To reduce the RS232 data rate) ; 2004-02-28 Created from DSCOPE (1 channel digital scope) ; Will support up to 4 digital channels but with ; a lower sustained data-rate ; "B" : Start sampling ; "X" : Stop sampling ; When the PIC is idle slowly blink the error led ; ; "CONTINIOUS SAMPLING MODE" ; The sampling rate is selectable from 2usec to 100 usec ; The maximum sustained rate is limited by the serial interface, the ; number of transitions per second which can be detected is a lot ; less than the resolution. ; A 115K serial interface limits the nr. of loggable transitions to ; 5750 events/second. The 256 event ringbuffer allows buffering of bursts ; but the sustained rate should be below the above mentioned value ; (avg. pulsewidth of 174 microseconds) ; A 500K serial interface (with an USB adapter) limits the nr. of loggable ; transitions to 25000 events/sec (avg. pulsewidth of 40 microseconds) ; Higher serial speeds (like 1Mbit) cause data loss at the PC side when a ; VCP (Virtual COM port) is used. ; For 8-bit sampling the sustained rate is 2/3 of the 4-bit rate ; For 2-bit sampling the sustained rate is twice the 4-bit rate ; ; "FAST SAMPLING MODE" ; High speed sampling does not work in continious mode but takes a fixed nr of ; samples. This will limit the amount of samples to the memory size available ; in the PIC (depends on type, from 1280 to 3840 bytes). ; After the sampling the data is transmitted. Sample intervals of 200nsec, ; 500nsec, 1usec and 2 usec are available. ; ; "CONTINOUS MODE" 4-BIT DATA PROTOCOL ; For each sample two bytes are sent containing the 8bit ; period (time since last sample) and the 4 channel values. ; ; bit7 = start bit ; bit6 = stop bit ; bit5..0 = data bits ; ; BYTE 0: bit7 = 1 (start) ; bit6 = 0 ; bit5 = bit7 of timestamp ; bit4 = bit6 of timestamp ; bit3 = PB3 status (Channel 3) ; bit2 = PB2 status (Channel 2) ; bit1 = PB1 status (Channel 1) ; bit0 = PB0 status (Channel 0) ; BYTE 1: bit7 = 0 ; bit6 = 1 (stop) ; bit5 = bit5 of timestamp ; bit4 = bit4 of timestamp ; bit3 = bit3 of timestamp ; bit2 = bit2 of timestamp ; bit1 = bit1 of timestamp ; bit0 = bit0 of timestamp ; ; "CONTINOUS MODE" 8-BIT DATA PROTOCOL ; For each sample three bytes are sent containing the 8bit ; period (time since last sample) and the 8 channel values. ; ; bit7 = start bit ; bit6 = stop bit ; bit5..0 = data bits ; ; BYTE 0: bit7 = 1 (start) ; bit6 = 0 ; bit5 = bit7 of timestamp ; bit4 = bit6 of timestamp ; bit3 = PB7 status (Channel 8) ; bit2 = PB6 status (Channel 7) ; bit1 = reserved (=0) ; bit0 = reserved (=0) ; ; BYTE 1: bit7 = 0 ; bit6 = 0 ; bit5 = PB5 status (Channel 6) ; bit4 = PB4 status (Channel 5) ; bit3 = PB3 status (Channel 4) ; bit2 = PB2 status (Channel 3) ; bit1 = PB1 status (Channel 2) ; bit0 = PB0 status (Channel 1) ; ; BYTE 2: bit7 = 0 ; bit6 = 1 (stop) ; bit5 = bit5 of timestamp ; bit4 = bit4 of timestamp ; bit3 = bit3 of timestamp ; bit2 = bit2 of timestamp ; bit1 = bit1 of timestamp ; bit0 = bit0 of timestamp ; ; "CONTINOUS MODE" 2-BIT DATA PROTOCOL ; For each sample one byte is sent containing a 5bit. ; Because there is no room for guard bits in this protocol after ; every 16 databytes a "control" byte is inserted which containes ; the checksum over the low 7 bits. The 8th bit is used to indicate ; a sampler buffer overrun ; ; DATABYTE: bit7 = bit5 of timestamp ; bit6 = bit4 of timestamp ; bit5 = bit3 of timestamp ; bit4 = bit2 of timestamp ; bit3 = bit1 of timestamp ; bit2 = bit0 of timestamp ; bit1 = PB0 status (Channel 1) ; bit0 = PB1 status (Channel 0) ; ; CONTROLBYTE: bit7 = 1 if Samplerbuffer overran ; o otherwise ; bit6..0 = Checksum of lower 7 bits ; ; FAST DATA PROTOCOL (FIXED PERIOD): ; Per sample the raw data is transmitted, first a trycount is ; transmitted, followed by the block length, followed by the ; raw data (No timing info, just PB statuses) ; For an 18F252 this will be 1280 bytes, for the 18F2525 3840 bytes ; ; Commands send to LOGAN: ; Please note all commands are echo'd back ! ; ; CMD ECHO ; ? tv Get Version (t=type, v=version) ; 0 Start 4-bit sampling, 2uSec interval ; 1 Start 4-bit sampling, 5uSec interval ; 2 Start 4-bit sampling, 10uSec interval ; 3 Start 4-bit sampling, 20uSec interval ; 4 Start 8-bit sampling, 2uSec interval ; 5 Start 8-bit sampling, 5uSec interval ; 6 Start 8-bit sampling, 10uSec interval ; 7 Start 8-bit sampling, 20uSec interval ; 8 Start 2-bit sampling, 10uSec interval ; 9 Stop Sampling ; D Set Trigger Delay for starttrigger ; Io Set Fast Scanoptions bit b45=width b123=speed ; J Fast Sampling using settings from 'I' command ; S Start serial monitor ; Vmb Setup Serial monitor (mask,baudrate) ; W Disable HiSpeed Trigger ; X Enable HiSpeed POST Trigger ; Y Enable HiSpeed START Trigger ; Ymp Set HiSpeed start trigger (mask,pattern) ; Zmpmp Set HiSpeed signal trigger (mask1, pattern1,mask2,pattern2) ; ; Can the PIC keep up with the 500Kbit and 1 Mbit datarate ? ; In 8-bit mode 74 cycles are needed to output 3 chars ; In 4-bit mode 60 cycles are needed to output 2 chars ; In 500K 1 byte is transmitted (10bit) in 50 microseconds, so to 2 bytes ; require a 100 usec and 3 bytes 150 usec. ; This will just work, HOWEVER, depending on the selected sampling rate ; a large part of the cycles will be spend in the interrupt routine. The ; minimum load (no state changes) is 9 cycles out of every 20 (at 2usec) ; or 9 cycles out of every 50 (at 5 usec). With fast changing signals we ; can not keep up the datarate. (Although the FIFO will help) ; PLEASE NOTE: some cycles are gained by optiziming the code after this ; calculation was done. ; ; TRIGGERING: ; ; In CONTINIOUS mode all the data is send over the link and triggering ; is done by the PC, this will allow all kinds of triggers, e.g. wait for ; a trigger, than throw away xx milliseconds, and then sample the data. ; ; In FAST mode data is gathered, send to the PC and then analysed. Because ; transmission can take a lot longer than sampling (e.g. sampling 2Kbyte ; will require a transmission time of 180 or 40 msec and the shortest trace ; is 400 microseconds, there is a large chance that the trigger is missed. ; Two triggers are available in fast mode: ; ; 1) A "data" trigger. Here the data is sampled, searched for the trigger, ; and if no match is found a new trace is started. Analyzing the trace ; will only take a few milliseconds (2 msec in 8bit mode, for 2048 samples), ; so there is a larger chance of finding the trigger. Please note that only ; the FIRST half of the buffer is scanned to insure there are pleny of samples ; after the trigger condition. ; This is a "hit-and-miss operation". Searching the buffer takes time so there ; is a chance that you will miss the event (especcially if it is a once only ; event. ; ; 2) A "start" trigger in which case the trigger initiates the sampling ; (after a small delay, up to 2 microseconds). The Start Trigger may be given ; on the datalines but also an External Trigger line can be used: PORTC.3 ; In this situation you will never miss the trigger as long as the trigger ; pulse is at least 1 microsecond. ; ---------------------------------------------------------------------------- IFDEF __18F252 LIST P=PIC18F252, F=INHX32 include CONFIG OSCS=OFF, OSC=HSPLL CONFIG PWRT=ON, BOR=ON, BORV=25 CONFIG WDT=OFF, WDTPS=128 CONFIG LVP=OFF, DEBUG=OFF #define FASTBUFFER 0x100 ; Start of Buffer, BANK0 contains vars #define FASTBUFFERSIZE .1280 #define PROCID '2' #define STOPBANK 0x06 ; Stop BANK for fast sampling (5 banks, 1-5) #define TRIGBANK 0x05 ; Only search bank 0-9 for a trigger pattern #define VARSTART 0x0000 ELSE IFDEF __18F2525 LIST P=PIC18F2525, F=INHX32 include CONFIG FCMEN=OFF, IESO = OFF, OSC=HSPLL CONFIG PWRT=ON, BOREN=ON, BORV=3 CONFIG WDT=OFF, WDTPS=128 CONFIG LPT1OSC=OFF, MCLRE=ON, PBADEN=OFF CONFIG XINST=OFF, DEBUG=OFF, LVP=OFF #define FASTBUFFER 0x000 ; Start of Buffer at begin of memory #define FASTBUFFERSIZE .3840 #define PROCID '3' #define STOPBANK 0x0F ; Stop BANK for fast sampling (14 banks, 1-14) #define TRIGBANK 0x0A ; Only search bank 0-9 for a trigger pattern #define VARSTART 0x0F00 ELSE ERROR "There is no supported processor selected. Verify selected processor." ENDIF ENDIF ; CBLOCK VARSTART SampleValue ; Local copies of sample which is to be send SampleTime ; over the serial interface Flags ; Flag word (multiple usage) Temp SCRATCH: 8 ; Scratch buffer for subroutines _t2period ; Timer 2 period count (LA sampling time base) _ticks ; ISR: tick counter (in sampling units) _LastVal ; ISR: Old and new PORTB values BlinkCounter ; Counter to controll the blink frequency TriggerMask,TriggerPattern ; Hi speed trigger mask & pattern TriggerMask2,TriggerPattern2; Hi speed trigger mask & pattern TriggerDelay:2 ; Counter for trigger delay TryCount ; Sample count (TEST) Sample1,Sample2 ; Sample values when searching for triggers FastMode ; Determines FAST sampling type ; bit 1,2,3: 000 = 200ns 001 = 500ns ; 010 = 1us 011 = 2us ; 100 = 5us 101 = 10us ; 110 = 111 = ; bit 4,5: 00 = 2 bit 01 = 4bit ; 10 = 8 bit 11 = ; bit 6: 0 = timed sampling ; 1 = transitional sampling (>2u) chk2bxfr ; Checksum for 2bit xfr mode cnt2bxfr ; Counter for 2bit xfr mode lst2bxfr ; Last sample for 2bit xfr mode SampleMask ; Used in FAST Transition sampling ; Variables below are for the RS232 monitor LastChannel ; Last channel for which data was send SerialMask ; Serial Channel mask (only '1' are processed) SerialSpeedIdx ; Serial Speed Index (0=300,1=1200,2=2400 etc..) ; The state visible to task-level code for the UART receivers rsr_chan: 8 ; Receiver shift registers for channels 0..7 rcv_ready ; Bitmap of channels with bytes ready frame_err ; Bitmap of channels with framing error overrun_err ; Bitmap of channels with overrun error ; The current inputs from the 8 serial ports curr_input ; The following bitmapped variable is used to track when a UART shift ; register is full and thus we have to check for the stop bit at the ; next sample time. full ; The following bitmapped variables maintain the state data for each of the ; channels. Note that each channel will always have exactly 1 one bit set ; in these variables to indicate what state that channel is in. wait_start ; Channel is waiting for start bit confirm_start ; Channel is verifying that it is in start bit ignore1 ; Channel is waiting for sample time ignore2 ; Channel is waiting for sample time sample ; Channel is sampling the input state stop_exp ; Channel is expecting the stop bit ; Temps used in computing the new state work new_wait_start new_ignore1 ENDC CBLOCK 0x100 ; Memory BANK1 CHDATA: .256 ; CHANNEL DATA BUFFER ENDC CBLOCK 0x200 ; Memory BANK2 CHTIME: .256 ; CHANNEL TIMING BUFFER ENDC #define VERSID '6' ; Version 6 (new number system !!) ; I/O pin descriptions #define ActivityLed PORTA,5 #define SelectHiSpeed PORTC,4 #define RTSline PORTC,5 ; Remote Clear To Send line #define RB_OVRRUN Flags,0 ; Ring Buffer OVeRRUN #define SAMPLE8 Flags,1 ; set = 8-bit sampling, clr = 4-bit sampling #define HI_PRETRIGGER Flags,2 ; Start trigger used in Hi-Speed mode ? #define HI_POSTTRIGGER Flags,3 ; Data trigger used in Hi-Speed mode ? #define HALFBYTE Flags,4 ; Used to determine if startpos is at half byte #define SAMPLE2 Flags,5 ; Used to indicate 2bit sampling #define XTriggerPin PORTC,3 ; I/O line used as external start trigger #define MBC_TIMEOUT .50 ; MultiByteCommand timeout ; ---------------------------------------------------------------------------- ; Equates, I/O, vars ; ---------------------------------------------------------------------------- RESET_V EQU 0x0000 ; Address of RESET Vector ISRH_V EQU 0x0008 ; Address of Hi-Interrupt Vector ISRL_V EQU 0x0018 ; Address of Lo-Interrupt Vector CLOCKFREQ EQU .400000 ; 40 MHz Clock (10 MHz X-tal) #define PERIOD2US .19 ; Count to 20 #define PERIOD5US .49 ; Count to 50 #define PERIOD10US .99 ; Count to 100 #define PERIOD20US .199 ; Count to 199 ORG RESET_V ; RESET vector location goto START ; Jump to program start ORG ISRH_V ; Interrupt vector location goto SM_INTERRUPT ORG ISRL_V ; Interrupt vector location ; ---------------------------------------------------------------------------- ; Interupt Handler used when in Logic Analyser mode, ; The only known interrupt source is the TIMER2 timout (a new sample ; should be taken ; The routine is kept as short as possible as this has a direct impact ; on the maximum sampling rate ; - Size of ringbuffer is kept at 256 (automatic rollover) ; - FSR1 and FSR2 are dedicated to this routine (Ringbuffer ; insertion pointers ; - FSR holds the extraction pointer ; ; Three paths are possible in this routine: (excluding call overhead) ; No Action = 9 cycles { Timer tick } ; Rollover = 14 cycles { Timer wrap message posted to queue) ; Change Detect = 18 cycles { Port change detected } ; For a 40 MHz PIC we can execute 10 instructions per microsecond ; so the shortest sampling interval is 2 microseconds !! ; ---------------------------------------------------------------------------- LA_INTERRUPT bcf PIR1, TMR2IF ; Clr Timer2 interrupt ; Always sample the lines to achieve ; a consistent delay since the int occurred movf PORTB,W ; Sample I/O lines movwf INDF1 ; an place result in ringbuffer infsnz _ticks,F bra _Add2Queue ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? retfie FAST ; No change, just return xorwf _LastVal,F ; _LastVal now holds latest sample _Add2Queue movf _ticks,W ; Get Tick Count movwf INDF2 ; store in ringbuffer2 incf FSR2L,F ; increment, auto rollover at 256 clrf _ticks ; Reset tick counter incf FSR1L,F ; increment, auto rollover at 256 movf FSR0L,W ; compare with extraction ptr cpfseq FSR1L,W ; check for buffer full retfie FAST ; NO, return from interrupt ; Internal ringbuffer full, Stop Sampling and raise an error condition ; The DOSAMPLE routine will switch back to IDLE mode after all events ; from the queue are transmitted to the host BufferFull: call StopSampling ; Disable ints decf FSR1L,F ; free last entry again decf FSR2L,F ; (otherwise buffer is not flushed) bsf RB_OVRRUN ; Set error flag retfie FAST ; return from interrupt ; *************************** BEGIN OF MAIN PROGRAM *************************** START ; POWER_ON Reset (Beginning of program) clrf STATUS ; Do initialization, Select bank 0 clrf INTCON ; Clear int-flags, Disable interrupts clrf PIR1 clrf INTCON2 clrf INTCON3 clrf PCLATH clrf PCLATU ; Point Bank Select Register movlb high SampleValue ; to correct mempage (0for 252, 14 for 2525) bsf RCON,IPEN ; Enable interrupt priorities clrf Flags movlw 0x07 movwf ADCON1 ; DISABLE a/d clrf PORTA ; ALL PORT output should output Low. clrf PORTB clrf PORTC bsf ActivityLed ; Turn activity led off bcf INTCON2,NOT_RBPU; Enable weak pull-ups MOVLW b'00001111' ; Configure RA0-3 as input, RA4-5 as outputs MOVWF TRISA movlw b'11111111' ; Configure RB0-7 as inputs movwf TRISB movlw b'10111111' ; RC5=I (RTS) RC6=O (TX) RC7=I (RX) movwf TRISC movlw 0x03 ; RS-232 monitor: Default only sample RB0 and RB1 movwf SerialMask,BANKED movlw 4 movwf SerialSpeedIdx ; RS-232 monitor: Default speed is 4800 Bd call Delay ; Small startup delay ; START OF TESTCODE, USED ONLY IN THE DEBUGGER/SIMULATER ; movlw b'00010011' ; 8 bit 2000nsec test ; movlw b'10000101' ; movwf FastMode ; goto FastSample ; goto SmartSample ; goto StartSampling2 ; goto StartSerial ; movlw 0x00 ; movwf TriggerMask ; movwf TriggerMask2 ; movlw 0x00 ; movwf TriggerPattern ; movlw 0x08 ; movwf TriggerPattern2 ; bsf HI_PRETRIGGER ; goto FastSample1000 ; goto SearchTriggerF4 ; END OF TESTCODE, USED ONLY IN THE DEBUGGER/SIMULATER ; ---------------------------------------------------------------- ; Check Baud rate to use, if HIGH use USB BaudRate (500kbit) ; if LOW use SERIAL Baudrate (115kbit) ; ---------------------------------------------------------------- ; Setup Serial Port movlw .21 ; 115K, No Parity, 1 Stop Bit btfsc SelectHiSpeed ; Test baud rate select pin movlw .4 ; 500K, No Parity, 1 Stop bit movwf SPBRG movlw b'00100100' ; brgh = 1 high speed datarates movwf TXSTA ; enable Async Transmission, set brgh movlw b'10010000' ; enable Async Reception movwf RCSTA IFDEF __18F2525 clrf BAUDCON ; Select "compatibility mode" ENDIF clrf TriggerMask ; Clear triggers for hi-speed mode clrf TriggerPattern clrf TriggerMask2 clrf TriggerPattern2 clrf TriggerDelay clrf TriggerDelay+1 clrf TryCount clrf BlinkCounter ; ---------------------------------------------------------------------------- ; Main Idle Loop, check received characters and take action ; TODO: Add recovery from UART errors ; ---------------------------------------------------------------------------- IDLE btfsc PIR1,RCIF ; Character in receiver buffer ? bra ParseChar ; Yes incf BlinkCounter,f btfss BlinkCounter,5 ; Selecting the proper bit gives control bsf ActivityLed ; over the blink frequency btfsc BlinkCounter,5 ; [Ugly, but works] bcf ActivityLed call Delay bra IDLE ParseChar movf RCREG,W ; Get character movwf SCRATCH ; Save for later use call SendChar ; Echo char movf SCRATCH,W xorlw 'I' ; 'I' = Get settings for FAST sampling btfsc STATUS,Z ; bit0..2 sampling speed, ; bit3..5 sampling width goto GetFastMode ; bit7 sampling type (timed/onchange) movf SCRATCH,W xorlw 'J' ; 'J' = Fast sample with current setting btfsc STATUS,Z goto FastSample movf SCRATCH,W xorlw 'W' ; 'W' = Disable Trigger btfsc STATUS,Z goto DisableTrigger movf SCRATCH,W xorlw 'X' ; 'X' = Enable PostTrigger btfsc STATUS,Z goto EnablePostTrigger movf SCRATCH,W xorlw 'Y' ; 'Y' = Enable StartTrigger btfsc STATUS,Z goto EnableStartTrigger movf SCRATCH,W xorlw 'Z' ; 'Z' = Receive Trigger btfsc STATUS,Z goto GetTrigger movf SCRATCH,W xorlw 'D' ; 'D' = Receive Triggerdelay btfsc STATUS,Z goto GetTriggerDelay movf SCRATCH,W xorlw '?' ; Return ID bz SendVersion movf SCRATCH,W xorlw '0' ; '0' = Sample at 2 uSec intervals bz StartSampling2 movf SCRATCH,W xorlw '1' ; '1' = Sample at 5 uSec intervals bz StartSampling5 movf SCRATCH,W xorlw '2' ; '2' = Sample at 10 uSec intervals bz StartSampling10 movf SCRATCH,W xorlw '3' ; '3' = Sample at 20 uSec intervals bz StartSampling20 movf SCRATCH,W xorlw '4' ; '4' = Sample at 2 uSec intervals (8bit) bz StartSampling2 movf SCRATCH,W xorlw '5' ; '5' = Sample at 5 uSec intervals (8bit) bz StartSampling5 movf SCRATCH,W xorlw '6' ; '6' = Sample at 10 uSec intervals (8bit) bz StartSampling10 movf SCRATCH,W xorlw '7' ; '7' = Sample at 20 uSec intervals (8bit) bz StartSampling20 movf SCRATCH,W xorlw '8' ; '8' = Sample at 10 uSec intervals (2bit) bz StartSampling10A movf SCRATCH,W xorlw 'S' ; 'S' = Serial Monitor 4800 Bd btfsc STATUS,Z goto StartSerial movf SCRATCH,W xorlw 'V' ; 'V' = Setup Serial Parameters btfsc STATUS,Z goto GetSerialPars goto IDLE ; loop over serial input ; ---------------------------------------------------------------------------- ; SendVersion will send two characters to the host: ; The TYPE ID (1=16F628, 2=18F252, 3=18F2525) ; The VERSION ID (8) ; ---------------------------------------------------------------------------- SendVersion movlw PROCID call SendChar movlw VERSID call SendChar goto IDLE ; ---------------------------------------------------------------------------- ; Main sampling loop, check the event ring buffer for available data ; If events are found encode and transmit them ; If a STOP_SAMPLING character is received stop the sampling and ; switch to idle mode ; ---------------------------------------------------------------------------- DOSAMPLE btfss PIR1,RCIF ; Character in receiver buffer ? bra CheckBuffer ; No movf RCREG,W ; Get character xorlw '9' ; Check for '9' (stops sampling) bnz CheckBuffer ; No call StopSampling ; YES, stop interrupts movlw '9' call SendChar goto IDLE ; and await next command CheckBuffer movf FSR1L,W subwf FSR0L,W ; subtract extract-insert pointer bz CheckOverrun ; No data in buffer, Do Error Check ; Data available, retreive, process and transmit it ; FSR0 points to the buffer where we should extract the data movlw 1 movwf FSR0H ; Value buffer is in BANK1 movf INDF0,W movwf SampleValue ; Get I/O Status movlw 2 movwf FSR0H ; Timing buffer is in BANK2 movf INDF0,W movwf SampleTime ; Get Time info ; Free the Ringbuffer entry, we have a copy in CV ; note that the increment could be interrupted so always ; keep the ptr valid !! incf FSR0L ; auto wrap at 256 ; Data is now in local buffers, encode and send the data btfsc SAMPLE2 ; Experimental 2bit mode? goto exp2bit ; Use dirty solution btfss SAMPLE8 rcall SendBIN4 ; Send frame in 4bit binary format btfsc SAMPLE8 rcall SendBIN8 ; Send frame in 8bit binary format bra DOSAMPLE exp2bit rcall SendBIN2 ; Send frame in 2bit binary format bra DOSAMPLE ; Experimental code CheckOverrun btfss RB_OVRRUN ; RingBuffer overrun detected bra DOSAMPLE ; No, continue sampling ; The interrupt buffer has overflown, there are however ; still 254 valid samples in the ringbuffer, so first transmit ; them before tranmitting the abort character ; Copy of code above (not in subroutine calls for speed reasons) movlw .254 movwf TryCount Flush btfss PIR1,RCIF ; Character in receiver buffer ? bra FlushSample ; No movf RCREG,W ; Get character xorlw '9' ; Check for '9' (stops sampling) bnz CheckBuffer ; No call StopSampling ; YES, stop interrupts movlw '9' call SendChar goto IDLE ; and await next command FlushSample movlw 1 movwf FSR0H ; Value buffer is in BANK1 movf INDF0,W movwf SampleValue ; Get I/O Status movlw 2 movwf FSR0H ; Timing buffer is in BANK2 movf INDF0,W movwf SampleTime ; Get Time info ; Free the Ringbuffer entry, we have a copy in CV ; note that the increment could be interrupted so always ; keep the ptr valid !! incf FSR0L ; auto wrap at 256 ; Data is now in local buffers, encode and send the data btfss SAMPLE8 rcall SendBIN4 ; Send frame in 4bit binary format btfsc SAMPLE8 rcall SendBIN8 ; Send frame in 8bit binary format decfsz TryCount,F bra Flush movlw 0xFF ; YES call SendChar ; Send Abort character goto IDLE ; and switch to IDLE ; ---------------------------------------------------------------------------- ; StartSamplingxxx: ; Load the required period and pre- and post-scale factors ; and proceed to StartSampling ; ---------------------------------------------------------------------------- StartSampling2: ; 2 usec sampling movlw PERIOD2US ; Get Period movwf _t2period rcall StartSampling bra DOSAMPLE StartSampling5: ; 5 usec sampling movlw PERIOD5US ; Get Period movwf _t2period rcall StartSampling bra DOSAMPLE StartSampling10: ; 10 usec sampling movlw PERIOD10US ; Get Period movwf _t2period rcall StartSampling bra DOSAMPLE StartSampling20: ; 20 usec sampling movlw PERIOD20US ; Get Period movwf _t2period rcall StartSampling bra DOSAMPLE ; Dirty patch to test the 2bit normal mode StartSampling10A: movlw PERIOD10US ; Get Period movwf _t2period rcall StartSamplingA bra DOSAMPLE StartSamplingA: bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors yet bcf SAMPLE8 ; SCRATCH still contains the command, bsf SAMPLE2 clrf chk2bxfr ; Clear extra counters for 2bit clrf cnt2bxfr ; transfer mode bra _ss1 ; ---------------------------------------------------------------------------- ; Start Sampling: ; Load T2 with the requested sample rate and enable the interrupts ; ---------------------------------------------------------------------------- StartSampling bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors yet bcf SAMPLE2 bcf SAMPLE8 ; SCRATCH still contains the command movlw '4' subwf SCRATCH,W btfss STATUS,N ; 8bit sampling has opcodes 3,4&5 bsf SAMPLE8 ; Set flag if bit2 is set in the command _ss1 LFSR 0,CHDATA ; FSR1 -> Ringbuffer (extr. ptr) LFSR 1,CHDATA ; FSR2 -> Ringbuffer (ins. ptr) LFSR 2,CHTIME ; FRS2 -> Ringbuffer (ins. ptr) clrf _ticks ; clear tick counter bcf RB_OVRRUN ; Clear overrun flag movf PORTB,W ; Sample input lines xorlw 0xff ; invert data movwf _LastVal ; Enforce transmission of first frame clrf T2CON ; Stop Timer2, Prescaler = 1:1, Postscaler = 1:1 clrf TMR2 ; Clear Timer2 register clrf INTCON ; Disable interrupts clrf PIE1 ; Disable peripheral interrupts clrf PIR1 ; Clear peripheral interrupts Flags bcf IPR1,TMR2IP ; Assign low priority interrupt movf _t2period,W ; Get Period value movwf PR2 bsf PIE1,TMR2IE ; Timer 2 interrupt on bsf INTCON,PEIE ; Pheriperal interrupts enabled bsf INTCON,GIE ; Global interrupts enabled bsf T2CON, TMR2ON ; Timer2 starts to increment return ; ---------------------------------------------------------------------------- ; StopSampling: ; Enable the timer and change detect interrupts (so start sampling) ; ---------------------------------------------------------------------------- StopSampling bsf T2CON, TMR2ON ; Stop Timer2 clrf INTCON ; Disable all interrupts bcf ActivityLed ; Turn LED off return ; ---------------------------------------------------------------------------- ; SendChar will send the character in W. ; It only tests if TXREG is available, it does not wait on completion ; if the transmission. ; Tests remote Clear to Send line before initiating a send ; ---------------------------------------------------------------------------- SendChar btfsc RTSline ; Request to send should be low bra SendChar WtHere btfss PIR1,TXIF ; TXREG is empty if hi bra WtHere movwf TXREG ; send data in W return ; ---------------------------------------------------------------------------- ; SENDCHAR_I is the INLINE version of the same routine ; (Saves 4 cycles in call/return overhead) ; ---------------------------------------------------------------------------- SENDCHAR_I MACRO btfsc RTSline ; Request to send should be low bra $-2 btfss PIR1,TXIF ; TXREG is empty if hi bra $-2 movwf TXREG ; send data in W ENDM SendBIN4 movf SampleTime,W ; Get Time stamp andlw 0xC0 ; Isolate Bit7 & Bit6 movwf Temp rrncf Temp,F rrncf Temp,W andlw 0x30 ; Mask of BIT 7 & Bit6 iorlw 0x80 ; Add startbit movwf Temp movf SampleValue,W ; Get PB0-PB3 andlw 0x0F iorwf Temp,W ; insert high nibble SENDCHAR_I ; FIRST BYTE OF FRAME movf SampleTime,W andlw 0x3F ; mask of bit5 - bit0 iorlw 0x40 ; add stop bit SENDCHAR_I ; LAST BYTE OF FRAME return SendBIN8 movf SampleTime,W ; Get Time stamp andlw 0xC0 ; Isolate Bit7 & Bit6 movwf Temp rrncf Temp,F rrncf Temp,W andlw 0x30 ; Mask of BIT 7 & Bit6 iorlw 0x80 ; Add startbit movwf Temp swapf SampleValue,W ; Get PB6-PB7 andlw 0x0C iorwf Temp,W ; insert high nibble SENDCHAR_I ; FIRST BYTE OF FRAME movf SampleValue,W ; Get PB0-PB5 andlw 0x3F SENDCHAR_I ; SECOND BYTE OF FRAME movf SampleTime,W andlw 0x3F ; mask of bit5 - bit0 iorlw 0x40 ; add stop bit SENDCHAR_I ; LAST BYTE OF FRAME return ; Send data when in 2 bit mode, as the frame only hold 6 bits ; of time information and there could be a time > 64 we may have ; a message may expand to more characters. Also keep track of ; send count to allow insertion of the control bytes SendBIN2 movf SampleTime,W bz _sb2MoreBytes ; Time == 256 _sb2loop movlw .64 cpfslt SampleTime bra _sb2MoreBytes ; Time >= 64 _sb2LastByte rlncf SampleTime,F ; Shift to correct pos. rlncf SampleTime,W movwf Temp movf SampleValue,W andlw 0x03 ; Get PB0&PB1 movwf lst2bxfr ; Save for next time iorwf Temp,W call SendCharCS return _sb2MoreBytes movf lst2bxfr,W ; Time > 64 so send T=64 with last value call SendCharCS movlw .64 subwf SampleTime,F ; Subtract amount sent bnz _sb2loop ; More time left, so try again return ; Special for 2 bit: track Checksum and insert control bytes SendCharCS addwf chk2bxfr ; Update Checksum SENDCHAR_I ; Send current byte incf cnt2bxfr ; Increment databyte count btfss cnt2bxfr,3 ; 16 bytes sent ? return movf chk2bxfr,W ; Yes, sent Checksum andlw 0x7F ; with bit7 cleared SENDCHAR_I clrf cnt2bxfr ; Clear count & checksum clrf chk2bxfr return ; ---------------------------------------------------------------------------- ; +/- 10 millisecond delay (Used to blink the status led) ; ---------------------------------------------------------------------------- Delay movlw .131 movwf SCRATCH movwf SCRATCH+1 _dlay: decfsz SCRATCH,f bra _dlay decfsz SCRATCH+1,f bra _dlay return ; ---------------------------------------------------------------------------- ; GetTrigger: receive 4 additional chars and set them as the trigger pattern ; both characters should be received within the timeout period (in order ; to prevent a hangup in this routine) ; ---------------------------------------------------------------------------- GetTrigger lfsr 1,TriggerMask ; FSR1 to start of data to get movlw .4 ; 4 bytes expected rcall GetCmdData btfss STATUS,C ; Carry clear: data rcvd OK goto IDLE clrf TriggerMask ; An error occured, clear the trigger modes clrf TriggerMask2 goto IDLE ; ---------------------------------------------------------------------------- ; GetTriggerDelay: receive 2 additional chars and set them as the 16 bit ; trigger delay. Both characters should be received within the timeout period ; (in order to prevent a hangup in this routine) Format is Lo-Hi ; ---------------------------------------------------------------------------- GetTriggerDelay lfsr 1,TriggerDelay ; FSR1 to start of data to get movlw .2 ; 2 bytes expected rcall GetCmdData btfss STATUS,C ; Carry clear: data rcvd OK goto IDLE clrf TriggerDelay ; An error occured, clear the trigger delay clrf TriggerDelay+1 goto IDLE ; ---------------------------------------------------------------------------- ; GetFastMode: receive 1 additional char which specifies the sampling speed ; and sampling width (new command which replaces the old fast sampling commands ; ---------------------------------------------------------------------------- GetFastMode lfsr 1,FastMode ; FSR1 to start of data to get movlw .1 ; 1 byte expected rcall GetCmdData goto IDLE ; ---------------------------------------------------------------------------- GetCmdData bsf ActivityLed movwf Temp ; W contains bytes to receive _NextCDbyte movlw MBC_TIMEOUT ; Set timeout period movwf BlinkCounter _WaitCDbyte btfsc PIR1,RCIF ; Character in receiver buffer ? bra _SaveCDbyte ; Yes call Delay ; 10 msec delay decfsz BlinkCounter,F bra _WaitCDbyte bsf STATUS,C ; TimeOut, return with Carry set return _SaveCDbyte movf RCREG,W ; Get character movwf POSTINC1 ; and save rcall SendChar ; Echo char back to host decfsz Temp,F ; All bytes received ? bra _NextCDbyte bcf STATUS,C ; Yes, return with Carry clear return DisableTrigger clrf TriggerMask clrf TriggerMask2 bcf HI_PRETRIGGER bcf HI_POSTTRIGGER goto IDLE EnablePostTrigger bcf HI_PRETRIGGER bsf HI_POSTTRIGGER goto IDLE EnableStartTrigger bsf HI_PRETRIGGER bcf HI_POSTTRIGGER goto IDLE ; ---------------------------------------------------------------------------- ; SendFastResult ; Dumps the data captured during a fast capture mode ; We could compress the datastream so allow a faster ; transmission. ; Format: 1 BYTE TRYCOUNT (nr of tries for the trigger occurred) ; 2 BYTES DATALENGTH (Depends on processor used) ; N BYTES The data itself (1280 or 3840 bytes) ; ---------------------------------------------------------------------------- SendFastResult movf TryCount,W rcall SendChar movlw high FASTBUFFERSIZE rcall SendChar movlw low FASTBUFFERSIZE rcall SendChar lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _sfrloop movf POSTINC1,W ; Get a sample rcall SendChar ; and transmit movf FSR1L,W btfsc STATUS,Z ; Every 256 bytes call Delay ; insert a 10 millisecond delay movlw STOPBANK ; Stop position of input buffer cpfseq FSR1H ; Loop all samples bra _sfrloop return ; ---------------------------------------------------------------------------- ; DoStartTrigger: Only used in FAST (Hi-Speed) mode ; Wait for a start trigger before fast sampling is started ; Any received serial char will abort the wait and return with the Carry set ; ---------------------------------------------------------------------------- DoStartTrigger bcf STATUS,C ; Clear the carry btfss HI_PRETRIGGER return ; StartTriggering is not Enabled movf TriggerMask,W ; if MASK == 0 use external trigger signal bnz _waitTrigger ; External trigger should be a rising edge or falling edge on PORTC.3 ; so set the correct patterns in TriggerPattern and TriggerPattern1 ; if the initial TriggerPattern == 0 we look for a rising edge, else ; for a falling edge movf TriggerPattern,W bz _FallingEdge _RaisingEdge btfss XTriggerPin ; First must be low bra _RaisingEdge2 btfss PIR1,RCIF ; Character in receiver buffer ? bra _RaisingEdge ; No, try again bra _waitAborted ; Yes, abort _RaisingEdge2 btfsc XTriggerPin ; Then must be high return ; Trigger condition met btfss PIR1,RCIF ; Character in receiver buffer ? bra _RaisingEdge2 ; No, try again bra _waitAborted ; Yes, abort _FallingEdge btfsc XTriggerPin ; First must be high bra _FallingEdge2 btfss PIR1,RCIF ; Character in receiver buffer ? bra _FallingEdge ; No, try again bra _waitAborted ; Yes, abort _FallingEdge2 btfss XTriggerPin ; Then must be low goto _TriggerFound btfss PIR1,RCIF ; Character in receiver buffer ? bra _FallingEdge2 ; No, try again bra _waitAborted ; Yes, abort ; Trigger should occur on one or more dataline ; At the moment only works for a single edge change !!!! ; should be rewritten to match the "Search.." Routines _waitTrigger movf PORTB,W andwf TriggerMask,W ; Check if 1st trigger condition met xorwf TriggerPattern,W bz _waitTrigger2 btfss PIR1,RCIF ; Character in receiver buffer ? bra _waitTrigger ; No, try again bra _waitAborted ; Yes, abort _waitTrigger2 movf TriggerMask2,W btfsc STATUS,Z goto _TriggerFound ; Trigger found (1 pattern) andwf PORTB,W ; Check if 2nd trigger condition met xorwf TriggerPattern2,W btfsc STATUS,Z goto _TriggerFound ; 2nd pattern matched btfss PIR1,RCIF ; Character in receiver buffer ? bra _waitTrigger2 ; No _waitAborted bsf STATUS,C movf RCREG,W ; Yes: Get character return ; Abort char received _TriggerFound movf TriggerDelay,W xorwf TriggerDelay+1,W btfsc STATUS,Z return ; No Delay after trigger _TriggerDelay nop ; Delay for TriggerDelay microseconds decf TriggerDelay ; Decrement low byte incfsz TriggerDelay,W ; Check for underflow incf TriggerDelay+1,F; Update decf TriggerDelay+1,F; Fixup movf TriggerDelay,W iorwf TriggerDelay+1,W; Set Z bit btfss STATUS,Z bra _TriggerDelay bcf STATUS,C return ; ---------------------------------------------------------------------------- ; SearchTriggerF8T (Search Trigger in FAST transitional mode) ; Searches the samples to see if a trigger is found in the data ; returns 0 if no trigger found, 1 if a trigger 2 and other on an abort ; After the scan a check for an abort is done ; ---------------------------------------------------------------------------- SearchTriggerF8T incf TryCount,F movf TriggerMask,W btfsc STATUS,Z retlw 1 ; Sanity check, Mask = 0 lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _srchloopFT movlw TRIGBANK ; Only search in the part of the buffer cpfseq FSR1H bra _scan1FT ; No, continue scanning btfss PIR1,RCIF ; Character in receiver buffer ? retlw 0 ; No, return "No Trigger Found" movf RCREG,W ; Yes: Get character retlw 2 ; Yes, return "Abort" _scan1FT movf TriggerMask,W ; Compare 1st trigger andwf POSTINC1,W movf POSTINC1,F ; Skip timedata xorwf TriggerPattern,W btfss STATUS,Z ; 1st trigger condition met bra _srchloopFT ; No, continue search movf TriggerMask2,W btfsc STATUS,Z retlw 1 ; Trigger found (1 pattern) andwf INDF1,W ; Compare 2nd trigger xorwf TriggerPattern2,W btfss STATUS,Z bra _srchloopFT retlw 1 ; Trigger found (2 patterns) ; ---------------------------------------------------------------------------- ; SearchTriggerF8 (Search Trigger in FAST 8-bit mode) ; Searches the samples to see if a trigger is found in the data ; returns 0 if no trigger found, 1 if a trigger 2 and other on an abort ; After the scan a check for an abort is done ; This function is also used in 2 and 4 bit transitional (compressed) fast ; sampling as these modes also store 1 sample/byte. (high timing bits are ; masked away by default due to the triggermask ; ---------------------------------------------------------------------------- SearchTriggerF8 incf TryCount,F movf TriggerMask,W btfsc STATUS,Z retlw 1 ; Sanity check, Mask = 0 lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _srchloopF8 movlw TRIGBANK ; Only search in the first half of the buffer cpfseq FSR1H bra _scan1F8 ; No, continue scanning btfss PIR1,RCIF ; Character in receiver buffer ? retlw 0 ; No, return "No Trigger Found" movf RCREG,W ; Yes: Get character retlw 2 ; Yes, return "Abort" _scan1F8 movf TriggerMask,W ; Compare 1st trigger andwf POSTINC1,W xorwf TriggerPattern,W btfss STATUS,Z ; 1st trigger condition met bra _srchloopF8 ; No, continue search movf TriggerMask2,W btfsc STATUS,Z retlw 1 ; Trigger found (1 pattern) andwf INDF1,W ; Compare 2nd trigger xorwf TriggerPattern2,W btfss STATUS,Z bra _srchloopF8 retlw 1 ; Trigger found (2 patterns) ; ---------------------------------------------------------------------------- ; SearchTriggerF4 (Search Trigger in FAST 4-bit mode) ; Searches the samples to see if a trigger is found in the data ; returns 0 if no trigger found, 1 if a trigger 2 and other on an abort ; After the scan a check for an abort is done ; Requires up to 4 msec on a 252, 14 msec on a 2525 ; ---------------------------------------------------------------------------- SearchTriggerF4 incf TryCount,F movf TriggerMask,W btfsc STATUS,Z retlw 1 ; Sanity check, Mask = 0 lfsr 1,FASTBUFFER ; FSR1 -> Databuffer swapf INDF1,W andlw 0x0F movwf Sample2 ; First sample bsf HALFBYTE ; At start of byte _srchloopF4 movlw TRIGBANK ; Only search in the first half of the buffer cpfseq FSR1H bra _scan1F4 ; No, continue scanning btfss PIR1,RCIF ; Character in receiver buffer ? retlw 0 ; No, return "No Trigger Found" movf RCREG,W ; Yes: Get character retlw 2 ; Yes, return "Abort" _scan1F4 movf Sample2,W movwf Sample1 ; Shuffle samples to match btfss HALFBYTE bra _GetHiNibble _GetLoNibble bcf HALFBYTE movf POSTINC1,W ; Both halves read andlw 0x0F movwf Sample2 bra _match _GetHiNibble bsf HALFBYTE swapf INDF1,W andlw 0x0F movwf Sample2 _match movf TriggerMask,W ; Compare 1st trigger andwf Sample1,W xorwf TriggerPattern,W btfss STATUS,Z ; 1st trigger condition met bra _srchloopF4 ; No, continue search _scan2 movf TriggerMask2,W btfsc STATUS,Z retlw 1 ; Trigger found (1 pattern) andwf Sample2,W xorwf TriggerPattern2,W btfss STATUS,Z bra _srchloopF4 retlw 1 ; Trigger found (2 patterns) ; ---------------------------------------------------------------------------- ; SearchTriggerF2 (Search Trigger in FAST 2-bit mode) ; Searches the samples to see if a trigger is found in the data ; returns 0 if no trigger found, 1 if a trigger 2 and other on an abort ; After the scan a check for an abort is done ; Requires up to 4 msec on a 252, 14 msec on a 2525 ; NOTE: Only used in FAST modes ; NOTE: NOT IMPLEMENTED, RETURNS TRUE ALWAYS ; ---------------------------------------------------------------------------- SearchTriggerF2 nop ; No code yet nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop nop retlw 1 ; Just return "Trigger Found" ; ---------------------------------------------------------------------------- ; FastSample: Get the current sample settings and goto the actual sampling ; routine using a computed jump ; ---------------------------------------------------------------------------- FastSample: movlw high JT_START movwf PCLATH rlncf FastMode,F ; Goto: 2 words per entry rlncf FastMode,W rrncf FastMode,F ; Restore FastMode andlw 0x7C JT_START addwf PCL,F goto IDLE ; 200 nsec, 2 bit goto IDLE ; 500 nsec, 2 bit goto FastSample1000C ; 1 usec, 2 bit goto FastSample2_2u ; 2 usec, 2 bit goto FastSample2_Nu ; 5 usec, 2 bit goto FastSample2_Nu ; 10 usec, 2 bit goto IDLE ; goto IDLE ; goto IDLE ; 200 nsec, 4 bit goto FastSample500B ; 500 nsec, 4 bit goto FastSample1000B ; 1 usec, 4 bit goto FastSample4_2u ; 2 usec, 4 bit goto FastSample4_Nu ; 5 usec, 4 bit goto FastSample4_Nu ; 10 usec, 4 bit goto IDLE ; goto IDLE ; goto FastSample200 ; 200 nsec, 8 bit goto FastSample500 ; 500 nsec, 8 bit goto FastSample1000 ; 1 usec, 8 bit goto FastSample8_2u ; 2 usec, 8 bit goto FastSample8_Nu ; 5 usec, 8 bit goto FastSample8_Nu ; 10 usec, 8 bit goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; goto IDLE ; JT_END IF ( (JT_START & 0x0FF) >= (JT_END & 0x0FF) ) ERROR "Error - Fast Sample jumptable crosses a page boundary" ENDIF FastSample8_2u bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE btfss FastMode,7 goto FastSampleX000 ; Sample at time interval goto FastSample8T2U ; Sample on changes FastSample8_Nu bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE btfss FastMode,7 goto FastSampleX000 ; Sample at time interval goto FastSampleTXU ; Sample on changes FastSample4_2u bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE btfss FastMode,7 goto FastSampleX000B ; Sample at time interval goto FastSample4T2U ; Sample on changes FastSample4_Nu bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE btfss FastMode,7 ; NOT IMPLEMENTED YET goto FastSampleX000B ; Sample at time interval goto FastSample4TNU ; Sample on changes FastSample2_2u bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE btfss FastMode,7 goto FastSampleX000C ; Sample at time interval goto FastSample2T2U ; Sample on changes FastSample2_Nu bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE btfss FastMode,7 ; NOT IMPLEMENTED YET goto FastSampleX000C ; Sample at time interval goto FastSample2TNU ; Sample on changes ; ---------------------------------------------------------------------------- ; FastSampleX000 takes 1280/3840 samples with a 2/5/10 microsecond interval ; Total sample duration: 2560/7680 usec for 2usec. ; ---------------------------------------------------------------------------- FastSampleX000: _sX000start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _sX000loop movff PORTB,POSTINC1 ; Sample input lines and place in buffer rcall _sX000Delay ; Waste time between samples movlw STOPBANK ; Stop position of input buffer cpfseq FSR1H bra _sX000loop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _sX000end ; No, skip call SearchTriggerF8 xorlw 1 ; Is TRIGGER found ? bz _sX000end ; if YES, send result xorlw 1 ; No Trigger found ? bz _sX000start ; if YES, sample again goto IDLE ; NO, ABORT _sX000end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; Delay routine to get the correct sample rate for 2, 5 and 10 usec in 8 bit FAST mode _sX000Delay movf FastMode,W andlw 0x07 xorlw 0x03 bz __2u8 movf FastMode,W andlw 0x07 xorlw 0x04 bz __5u8 __10u8 movlw .230 bra __Xu8loop __5u8 movlw .247 bra __Xu8loop __2u8 movlw .255 __Xu8loop addlw 1 bnz __Xu8loop bra $+2 ; 2 additional cycles return ; ---------------------------------------------------------------------------- ; FastSampleX000B takes 2560/7168 samples with a 2,5,10 microsecond interval (4bit) ; Total sample duration: 5120/14336 usec for 2usec ; ---------------------------------------------------------------------------- FastSampleX000B: _s2000Bstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _s2000Bloop swapf PORTB,W ; Sample input lines and place in buffer andlw 0xF0 ; mask off unused bits movwf INDF1 rcall _sX000BDelay1 ; Waste time between samples movf PORTB,W ; Take next sample andlw 0x0F ; Mask of unused bits iorwf INDF1,W ; Combine the two samples movwf POSTINC1 ; Store in buffer rcall _sX000BDelay2 ; Waste time between samples movlw STOPBANK ; Stop position of input buffer cpfseq FSR1H bra _s2000Bloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s2000Bend ; No, skip call SearchTriggerF4 xorlw 1 ; Is TRIGGER found ? bz _s2000Bend ; if YES, send result xorlw 1 ; No Trigger found ? bz _s2000Bstart ; if YES, sample again goto IDLE ; NO, ABORT _s2000Bend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; Delay routine to get the correct sample rate for 2, 5 and 10 usec in 4 bit FAST mode ; Used between odd and even sample _sX000BDelay1 movf FastMode,W andlw 0x07 xorlw 0x03 bz __2u41 ; 2 microsecond, 4bit, 1st loop movf FastMode,W andlw 0x07 xorlw 0x04 bz __5u41 __10u41 movlw .229 bra __Xu4loop1 __5u41 movlw .246 bra __Xu4loop1 __2u41 movlw .254 __Xu4loop1 addlw 1 bnz __Xu4loop1 bra $+2 ; 2 additional cycles return ; Used between even and odd sample _sX000BDelay2 movf FastMode,W andlw 0x07 xorlw 0x03 bz __2u42 ; 2 microsecond, 4bit, 2nd loop movf FastMode,W andlw 0x07 xorlw 0x04 bz __5u42 __10u42 movlw .230 bra __Xu4loop2 __5u42 movlw .247 bra __Xu4loop2 __2u42 movlw .255 __Xu4loop2 addlw 1 bnz __Xu4loop2 return ; ---------------------------------------------------------------------------- ; FastSampleX000C takes 5120/15360 samples with a 2,5,10 microsecond interval ; in 2bit mode, Total sample duration: 10240/30720 usec for 2usec sampling ; ---------------------------------------------------------------------------- FastSampleX000C _sX000Cstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _sX000Cloop movff PORTB,Temp ; Sample input lines and place in buffer rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf INDF1,F rcall _sX000CDelay1 movff PORTB,Temp ; Take next sample (2/4) rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf INDF1,F rcall _sX000CDelay1 movff PORTB,Temp ; Take next sample (3/4) rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf INDF1,F rcall _sX000CDelay1 movff PORTB,Temp ; Take next sample (4/4) rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf POSTINC1,F rcall _sX000CDelay2 movlw STOPBANK ; Stop position of input buffer cpfseq FSR1H bra _sX000Cloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _sX000Cend ; No, skip call SearchTriggerF2 xorlw 1 ; Is TRIGGER found ? bz _sX000Cend ; if YES, send result xorlw 1 ; No Trigger found ? bz _sX000Cstart ; if YES, sample again goto IDLE ; NO, ABORT _sX000Cend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; Delay routine to get the correct sample rate for 2, 5 and 10 usec in 2 bit FAST mode ; Used after 1-2-3 sample _sX000CDelay1 movf FastMode,W andlw 0x07 xorlw 0x03 bz __2u21 ; 2 microsecond, 2bit, 1st loop movf FastMode,W andlw 0x07 xorlw 0x04 bz __5u21 __10u21 movlw .230 bra __Xu2loop1 __5u21 movlw .247 bra __Xu2loop1 __2u21 movlw .255 __Xu2loop1 addlw 1 bnz __Xu2loop1 bra $+2 ; 2 additional cycles return ; Delay routine to get the correct sample rate for 2, 5 and 10 usec in 2 bit FAST mode ; Used after 4th sample _sX000CDelay2 movf FastMode,W andlw 0x07 xorlw 0x03 bz __2u22 ; 2 microsecond, 2bit, 2nd loop movf FastMode,W andlw 0x07 xorlw 0x04 bz __5u22 __10u22 movlw .231 nop bra __Xu2loop2 __5u22 movlw .248 nop bra __Xu2loop2 __2u22 nop return __Xu2loop2 addlw 1 bnz __Xu2loop2 return ; ---------------------------------------------------------------------------- ; FastSample1000 takes 1280/3840 samples with a 1 microsecond interval ; Total sample duration: 1280/3840 usec. ; ---------------------------------------------------------------------------- FastSample1000 bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE _s1000start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movlw STOPBANK ; Stop position of input buffer _s1000loop movff PORTB,POSTINC1 ; Sample input lines and place in buffer nop ; Waste 5 cycles (500 nsec) bra $+2 ; 2 cycles with 1 word bra $+2 cpfseq FSR1H bra _s1000loop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s1000end ; No, skip call SearchTriggerF8 xorlw 1 ; Is TRIGGER found ? bz _s1000end ; if YES, send result xorlw 1 ; No Trigger found ? bz _s1000start ; if YES, sample again goto IDLE ; NO, ABORT _s1000end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; ---------------------------------------------------------------------------- ; FastSample1000B takes 2560/7168 samples with a 1 microsecond interval (4bit) ; Total sample duration: 2560/7168 usec. ; ---------------------------------------------------------------------------- FastSample1000B bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE _s1000Bstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _s1000Bloop swapf PORTB,W ; Sample input lines and place in buffer andlw 0xF0 ; mask off unused bits movwf INDF1 ; nop ; Waste rest of the microsecond bra $+2 bra $+2 bra $+2 movf PORTB,W ; Take next sample andlw 0x0F ; Mask of unused bits iorwf INDF1,W ; Combine the two samples movwf POSTINC1 ; Store in buffer movlw STOPBANK ; Stop position of input buffer bra $+2 ; Waste rest of the microsecond cpfseq FSR1H bra _s1000Bloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s1000Bend ; No, skip call SearchTriggerF4 xorlw 1 ; Is TRIGGER found ? bz _s1000Bend ; if YES, send result xorlw 1 ; No Trigger found ? bz _s1000Bstart ; if YES, sample again goto IDLE ; NO, ABORT _s1000Bend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; ---------------------------------------------------------------------------- ; FastSample1000C takes 5120/15360 samples with a 1 microsecond interval (2bit) ; Total sample duration: 5120/15360 usec. ; ---------------------------------------------------------------------------- FastSample1000C bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE _s1000Cstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer _s1000Cloop movff PORTB,Temp ; Sample input lines and place in buffer rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf INDF1,F bra $+2 ; Waste rest of the microsecond bra $+2 movff PORTB,Temp ; Take next sample (2/4) rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf INDF1,F bra $+2 ; Waste rest of the microsecond bra $+2 movff PORTB,Temp ; Take next sample (3/4) rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf INDF1,F bra $+2 ; Waste rest of the microsecond bra $+2 movff PORTB,Temp ; Take next sample (4/4) rrcf Temp,F ; shift 2 bits to INDF1 rrcf INDF1,F rrcf Temp,F rrcf POSTINC1,F movlw STOPBANK ; Stop position of input buffer cpfseq FSR1H bra _s1000Cloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s1000Cend ; No, skip call SearchTriggerF2 xorlw 1 ; Is TRIGGER found ? bz _s1000Cend ; if YES, send result xorlw 1 ; No Trigger found ? bz _s1000Cstart ; if YES, sample again goto IDLE ; NO, ABORT _s1000Cend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; ---------------------------------------------------------------------------- ; FastSample500 takes 1280/3840 samples with a 500 nanosecond interval ; Total sample duration: 640/1920 usec. ; ---------------------------------------------------------------------------- FastSample500 bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE _s500start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movlw STOPBANK ; Stop position of input buffer _s500loop movff PORTB,POSTINC1 ; Sample input lines and place in buffer cpfseq FSR1H bra _s500loop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s500end ; No, skip call SearchTriggerF8 xorlw 1 ; Is TRIGGER found ? bz _s500end ; if YES, send result xorlw 1 ; No Trigger found ? bz _s500start ; if YES, sample again goto IDLE ; NO, ABORT _s500end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; ---------------------------------------------------------------------------- ; FastSample500B takes 2560/7680 samples with a 500 nanosecond interval ; Total sample duration: 1280/3840 usec. ; To allow a "FAST" boundary check a trick with FSR2 is used as counter ; NOTE: This will only work on the 252 as the 2525 buffer size exceeds 2K ; so two loops are used to count to 3840 for the 18F2525 ; ---------------------------------------------------------------------------- FastSample500B bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE _s500Bstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer IFDEF __18F2525 lfsr 2,0x000 ; Bit3 of FSR2 goes high after 2048 bytes lfsr 0,0x100 ; Bit3 of FSR0 goes high after 1792 bytes ELSE ;__18F252 lfsr 2,0x300 ; Bit3 of FSR2 goes high after 1280 bytes ENDIF _s500Bloop swapf PORTB,W ; Sample input lines to high 4 bits andlw 0xF0 ; mask off unused bits movwf INDF1 movlw 0x0F movf POSTINC2,F ; Increment FSR2 (Byte Counter) andwf PORTB,W ; Sample input lines to low bits iorwf POSTINC1,F ; Combine the two samples btfss FSR2H,3 ; If FSR2 reaches bank 8 bra _s500Bloop ; we have the correct nr of samples IFDEF __18F2525 ; More sampling to do with this processor nop ; waste extra cycle from the branch _s500Bloop2 swapf PORTB,W ; Sample input lines to high 4 bits andlw 0xF0 ; mask off unused bits movwf INDF1 movlw 0x0F movf POSTINC0,F ; Increment FSR2 (Byte Counter) andwf PORTB,W ; Sample input lines to low bits iorwf POSTINC1,F ; Combine the two samples btfss FSR0H,3 ; If FSR0 reaches bank 8 bra _s500Bloop2 ; we have the correct nr of samples ENDIF btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s500Bend ; No, skip call SearchTriggerF4 xorlw 1 ; Is TRIGGER found ? bz _s500Bend ; if YES, send result xorlw 1 ; No Trigger found ? bz _s500Bstart ; if YES, sample again goto IDLE ; NO, ABORT _s500Bend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ; ---------------------------------------------------------------------------- ; FastSample200 takes 1280/3840 samples with a 200 nanosecond interval ; Total sample duration: 256/768 usec. Only works with 40 MHz clock !! ; Uses inline code (only way to get that fast) ; ---------------------------------------------------------------------------- SAMPLE_8B_256T MACRO ; Sample 8 bits 256 times local ii=0; while ii<.256; movff PORTB,POSTINC1 ; Sample input lines and place in buffer ii += 1; endw ENDM FastSample200 bsf ActivityLed ; Turn activity led on bcf RB_OVRRUN ; No Errors clrf TryCount ; If a POST trigger is used, count nr of runs rcall DoStartTrigger ; Wait for a Start Trigger if enabled btfsc STATUS,C ; Test for abort goto IDLE _s200start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer ; lfsr 1,CHDATA ; FSR2 -> Ringbuffer (ins. ptr) SAMPLE_8B_256T ; 256 samples to BANK 1 SAMPLE_8B_256T ; 256 samples to BANK 2 SAMPLE_8B_256T ; 256 samples to BANK 3 SAMPLE_8B_256T ; 256 samples to BANK 4 SAMPLE_8B_256T ; 256 samples to BANK 5 IFDEF __18F2525 SAMPLE_8B_256T ; 256 samples to BANK 6 SAMPLE_8B_256T ; 256 samples to BANK 7 SAMPLE_8B_256T ; 256 samples to BANK 8 SAMPLE_8B_256T ; 256 samples to BANK 9 SAMPLE_8B_256T ; 256 samples to BANK A SAMPLE_8B_256T ; 256 samples to BANK B SAMPLE_8B_256T ; 256 samples to BANK C SAMPLE_8B_256T ; 256 samples to BANK D SAMPLE_8B_256T ; 256 samples to BANK E SAMPLE_8B_256T ; 256 samples to BANK F ENDIF btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _s200end ; No, skip call SearchTriggerF8 xorlw 1 ; Is TRIGGER found ? bz _s200end ; if YES, send result xorlw 1 ; No Trigger found ? btfsc STATUS,Z goto _s200start ; YES, sample again goto IDLE ; NO, ABORT _s200end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE ;***************************************************************************** ;* 8 BIT FAST TRANSITIONAL SAMPLING 8 BIT TO LOCAL BUFFEr * ;***************************************************************************** ; Can save a much longer duration in FAST MODE as only transitions are saved ; However; software overhead limits this to 2usec/sample or slower FastSample8T2U: _FS8T2start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movf PORTB,W movwf _LastVal clrf _ticks ; T = 0 movwf POSTINC1 ; Initial Value clrf POSTINC1 ; Initial Time _FS8T2loop movf PORTB,W ; Sample I/O lines to WREG infsnz _ticks,F bra _FS8T2addTick ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? bra _FS8T2noChange xorwf _LastVal,F ; _LastVal now holds latest sample movf _LastVal,W ; and in WREG bra $+2 ; Waste cycles to get 2u loop bra $+2 _FS8T2addBuffer movwf POSTINC1 ; Store sample in buffer movf _ticks,W ; Get Tick Count movwf POSTINC1 ; Store time in buffer clrf _ticks ; Reset tick counter movlw STOPBANK ; Check if sample buffer is full cpfseq FSR1H bra _FS8T2loop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _FS8T2end ; No, skip call SearchTriggerF8T xorlw 1 ; Is TRIGGER found ? bz _FS8T2end ; if YES, send result xorlw 1 ; No Trigger found ? bz _FS8T2start ; if YES, sample again goto IDLE ; NO, ABORT _FS8T2end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE _FS8T2addTick movwf _LastVal bra $+2 ; Waste cycles to get 2u loop bra $+2 nop bra _FS8T2addBuffer _FS8T2noChange bra $+2 ; Waste cycles to get 2u loop bra $+2 bra $+2 bra $+2 bra $+2 nop bra _FS8T2loop ;***************************************************************************** ;* EVENT SAMPLERS TO LOCAL BUFFER FOR 4 BIT (FAST for 2 usec) * ;***************************************************************************** ; In 4 bit mode for each sample 8 bits are used: the 4bit linestate and a 4bit ; timestamp. Can Save up to 3840 transitions and compress up to 16 times. FastSample4T2U movlw 0x0F ; 8 bits mode FIXED FOR NOW movwf SampleMask _FS4T2start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movf PORTB,W andwf SampleMask,W movwf _LastVal clrf _ticks ; T = 0 movwf POSTINC1 ; Initial Value/Time _FS4T2loop movf PORTB,W ; Sample I/O lines to WREG andwf SampleMask,W incf _ticks,F btfsc _ticks,4 ; Reached 16 ? bra _FS4T2addTick ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? bra _FS4T2noChange xorwf _LastVal,F ; _LastVal now holds latest sample (0000xxxx) swapf _ticks,W ; get tich count in high nibble andlw 0xF0 iorwf _LastVal,W bra $+2 ; Waste 2 cycles _FS4T2addBuffer movwf POSTINC1 ; Store sample in buffer clrf _ticks ; Reset tick counter movlw STOPBANK ; Check if sample buffer is full cpfseq FSR1H bra _FS4T2loop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _FS4T2end ; No, skip call SearchTriggerF8 ; 1 sample/byte xorlw 1 ; Is TRIGGER found ? bz _FS4T2end ; if YES, send result xorlw 1 ; No Trigger found ? bz _FS4T2start ; if YES, sample again goto IDLE ; NO, ABORT _FS4T2end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE _FS4T2addTick movwf _LastVal bra $+2 ; Waste cycles to get 2u loop bra $+2 nop bra _FS4T2addBuffer _FS4T2noChange bra $+2 ; Waste cycles to get 2u loop bra $+2 bra $+2 bra $+2 nop bra _FS4T2loop ;***************************************************************************** ;* EVENT SAMPLERS TO LOCAL BUFFER FOR 2 BIT (FAST for 2 usec) * ;***************************************************************************** ; In 2 bit mode for each sample 8 bits are used: the 2bit linestate and a 6bit ; timestamp. Can Save up to 3840 transitions and compress up to 64 times. FastSample2T2U movlw 0x03 movwf SampleMask _FS2T2start lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movf PORTB,W andwf SampleMask,W movwf _LastVal clrf _ticks ; T = 0 movwf POSTINC1 ; Initial Value/Time _FS2T2loop movf PORTB,W ; Sample I/O lines to WREG andwf SampleMask,W incf _ticks,F btfsc _ticks,6 ; Reached 64 ? bra _FS2T2addTick ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? bra _FS2T2noChange xorwf _LastVal,F ; _LastVal now holds latest sample (000000xx) rlncf _ticks,F ; get tich count in high 6 bits rlncf _ticks,W andlw 0xFC iorwf _LastVal,W nop _FS2T2addBuffer movwf POSTINC1 ; Store sample in buffer clrf _ticks ; Reset tick counter movlw STOPBANK ; Check if sample buffer is full cpfseq FSR1H bra _FS2T2loop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _FS2T2end ; No, skip call SearchTriggerF8 ; 1 sample/byte xorlw 1 ; Is TRIGGER found ? bz _FS2T2end ; if YES, send result xorlw 1 ; No Trigger found ? bz _FS2T2start ; if YES, sample again goto IDLE ; NO, ABORT _FS2T2end call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE _FS2T2addTick movwf _LastVal bra $+2 ; Waste cycles to get 2u loop bra $+2 nop bra _FS2T2addBuffer _FS2T2noChange bra $+2 ; Waste cycles to get 2u loop bra $+2 bra $+2 bra $+2 nop bra _FS2T2loop ; ---------------------------------------------------------------------------- FastSampleTXU: _FS8TNstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movf PORTB,W movwf _LastVal clrf _ticks ; T = 0 movwf POSTINC1 ; Initial Value clrf POSTINC1 ; Initial Time _FS8TNloop movf PORTB,W ; Sample I/O lines to WREG infsnz _ticks,F bra _FS8TNaddTick ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? bra _FS8TNnoChange xorwf _LastVal,F ; _LastVal now holds latest sample rcall _FS8TNDelay _FS8TNaddBuffer movf _LastVal,W ; WREG was destroyed in dlyloops movwf POSTINC1 ; Store sample in buffer movf _ticks,W ; Get Tick Count movwf POSTINC1 ; Store time in buffer clrf _ticks ; Reset tick counter movlw STOPBANK ; Check if sample buffer is full cpfseq FSR1H bra _FS8TNloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _FS8TNend ; No, skip call SearchTriggerF8T xorlw 1 ; Is TRIGGER found ? bz _FS8TNend ; if YES, send result xorlw 1 ; No Trigger found ? bz _FS8TNstart ; if YES, sample again goto IDLE ; NO, ABORT _FS8TNend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE _FS8TNaddTick movwf _LastVal ; Save sampled value rcall _FS8TNDelay bra _FS8TNaddBuffer _FS8TNnoChange bra $+2 bra $+2 bra $+2 nop rcall _FS8TNDelay bra _FS8TNloop _FS8TNDelay movf FastMode,W ; Waste cycles to get 5u or 10u loop andlw 0x07 xorlw 0x04 bz _FS8TN_5u _FS8TN_10u movlw .232 bra $+2 bra _FS8TNdloop _FS8TN_5u movlw .248 nop _FS8TNdloop addlw 1 bnz $-2 return ; ---------------------------------------------------------------------------- FastSample4TNU movlw 0x0F ; 8 bits mode FIXED FOR NOW movwf SampleMask _FS4TNstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movf PORTB,W andwf SampleMask,W movwf _LastVal clrf _ticks ; T = 0 movwf POSTINC1 ; Initial Value/Time _FS4TNloop movf PORTB,W ; Sample I/O lines to WREG andwf SampleMask,W incf _ticks,F btfsc _ticks,4 ; Reached 16 ? bra _FS4TNaddTick ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? bra _FS4TNnoChange xorwf _LastVal,F ; _LastVal now holds latest sample (0000xxxx) rcall _FS4TNDelay ; Waste cycles swapf _ticks,W ; get tick count in high nibble andlw 0xF0 iorwf _LastVal,W nop _FS4TNaddBuffer movwf POSTINC1 ; Store sample in buffer clrf _ticks ; Reset tick counter movlw STOPBANK ; Check if sample buffer is full cpfseq FSR1H bra _FS4TNloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _FS4TNend ; No, skip call SearchTriggerF8 ; 1 sample/byte !!! xorlw 1 ; Is TRIGGER found ? bz _FS4TNend ; if YES, send result xorlw 1 ; No Trigger found ? bz _FS4TNstart ; if YES, sample again goto IDLE ; NO, ABORT _FS4TNend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE _FS4TNaddTick movwf _LastVal rcall _FS8TNDelay movf _LastVal,W bra _FS4TNaddBuffer _FS4TNnoChange bra $+2 ; Waste cycles to get 2u loop bra $+2 bra $+2 bra $+2 rcall _FS4TNDelay bra _FS4TNloop _FS4TNDelay movf FastMode,W ; Waste cycles to get 5u or 10u loop andlw 0x07 xorlw 0x04 bz _FS4TN_5u _FS4TN_10u movlw .233 bra $+2 bra _FS4TNdloop _FS4TN_5u movlw .249 nop _FS4TNdloop addlw 1 bnz $-2 return ; ---------------------------------------------------------------------------- #define _FS2TNDelay _FS4TNDelay ; Same delay routine can be used FastSample2TNU movlw 0x03 movwf SampleMask _FS2TNstart lfsr 1,FASTBUFFER ; FSR1 -> Databuffer movf PORTB,W andwf SampleMask,W movwf _LastVal clrf _ticks ; T = 0 movwf POSTINC1 ; Initial Value/Time _FS2TNloop movf PORTB,W ; Sample I/O lines to WREG andwf SampleMask,W incf _ticks,F btfsc _ticks,6 ; Reached 64 ? bra _FS2TNaddTick ; Add event to queue on Tick rollover ; No Tick Rollover, check if any of the input lines have changed ; compare with the last sampled result xorwf _LastVal,W btfsc STATUS,Z ; Any bits changed ? bra _FS2TNnoChange xorwf _LastVal,F ; _LastVal now holds latest sample (000000xx) rcall _FS2TNDelay ; Waste cycles rlncf _ticks,F ; get tich count in high 6 bits rlncf _ticks,W andlw 0xFC iorwf _LastVal,W ; nop _FS2TNaddBuffer movwf POSTINC1 ; Store sample in buffer clrf _ticks ; Reset tick counter movlw STOPBANK ; Check if sample buffer is full cpfseq FSR1H bra _FS2TNloop btfss HI_POSTTRIGGER ; Search for a trigger pattern ? goto _FS2TNend ; No, skip call SearchTriggerF8 ; 1 sample/byte !!! xorlw 1 ; Is TRIGGER found ? bz _FS2TNend ; if YES, send result xorlw 1 ; No Trigger found ? bz _FS2TNstart ; if YES, sample again goto IDLE ; NO, ABORT _FS2TNend call SendFastResult ; Output the result bcf ActivityLed ; Turn activity led off goto IDLE _FS2TNaddTick movwf _LastVal rcall _FS2TNDelay ; Waste cycles movf _LastVal,W bra $+2 nop bra _FS2TNaddBuffer _FS2TNnoChange bra $+2 ; Waste cycles to get 2u loop bra $+2 bra $+2 bra $+2 rcall _FS2TNDelay ; Waste cycles bra _FS2TNloop ;_FS2TNDelay movf FastMode,W ; Waste cycles to get 5u or 10u loop ; andlw 0x07 ; xorlw 0x04 ; bz _FS2TN_5u ;_FS2TN_10u movlw .233 ; bra $+2 ; bra _FS2TNdloop ;_FS2TN_5u movlw .249 ; nop ;_FS2TNdloop addlw 1 ; bnz $-2 ; return ;***************************************************************************** ;************** MAIN CODE RELATED TO SERIAL MONITORING IS BELOW ************** ;***************************************************************************** ; ---------------------------------------------------------------------------- ; Interupt Handler used when in Serial Monitor mode, ; The only known interrupt source is the TIMER2 timout indicating ; the ports should be sampled (at 3 times the bitrate) ; Below follows the original comment from the original program which was grabbed ; from www.piclist.com. ; Some mods were made: Use of TMR2, port to 18F PIC and and maskable channels ; ---------------------------------------------------------------------------- ;======================================================================================= ; Copyright (c) 2000 by Robert V Ammerman (rammerman at -Remove-adelphia.net as of Jun 2003) ; ; This code may be used for any legal purpose, commerical or not. I only ask that you ; let me know if you use it and that you leave this copyright notice unchanged in ; your source code. ; ; Also, you understand that I have no liability if this code doesn't work as expected. ; ; Software UAR(no T) code developed by and used with the permission of: ; ; Robert V Ammerman ; RAm Systems ; (contract development of high performance, high function, low-level software) ; ;====================================================================================== ; ; The program works by handling timer interrupts at 3x the nominal bit rate and running a ; state machine for each channel to acquire the data. ; ; The first trick behind this code is the way the state machines are run: instead of ; handling each channel one at a time the program uses 'vertical arithmetic' to ; process all eight channels together. ; ; The second trick is the way that the program works thru processing the eight ; input bits on the channels, accumulating them into the 'receiver shift register' ; variables, and determining when a byte has been completely received. This is done ; using only 3 instructions per channel. ; ; Using these two tricks results in code that uses only 76 instructions per interrupt, ; including context save and restore, but not interrupt latency. Since interrupts ; are generated every 174 instructions this leaves about 54 percent of the CPU available ; for 'task level' code. ; ; One important thing to note: since this code does _not_ double buffer the receiver, ; task level code must process a received byte within 4/3 of a bit time (approximately ; 390 task level instructions), otherwise the overrun flag will be set for that channel. ; ; NOTES BY WIM: ; The following changes were made: ; Use of TMR2 which avoids the need to reload the timer (Saves 2 cycles) ; Use of an 18F PIC avoids the need to save/unsave registers (Saves 7 cycles) ; So the interrupt now executes in 69 instructions ; Use of an 18F PIC allows 19k2 sampling as an 18F is 10Mips vs 5MIPS for a 16F pic ; 4/3 bit time still apllies. SM_INTERRUPT: bcf PIR1, TMR2IF ; Clear Timer2 interrupt comf PORTB,W ; Get current input state movwf curr_input ; Save a copy movwf work ; Process all the inputs. ; Note that we only shift in bits for channels that are in the 'sample' state. rcv_chan MACRO n ; The next instruction does two things: ; 1: It puts 'receive shift register full' status, if any, ; for the previous channel into the high bit of 'work'. ; 2: It puts the input data bit for the current channel into ; carry. rrcf work,F ; See if this channel is ready to sample btfsc sample,n ; Do we need a new bit? ; If this channel is ready to sample, the following instruction will be ; executed to perform two functions: ; 1: It puts the input data bit into the receiver shift register. ; 2: It puts the 'receive shift register full' status into carry. rrcf rsr_chan+n,F ; Yes, move it in ENDM rcv_chan 0 rcv_chan 1 rcv_chan 2 rcv_chan 3 rcv_chan 4 rcv_chan 5 rcv_chan 6 rcv_chan 7 ; At this point 'work' contains the 'receive shift register full' bits for ; channels 0..6 (in bits 1..7) and carry has the bit for channel 7. rrcf work,W ; Bring in channel 7's ;'receive shift register full' bit ; Note that the bits in WREG that correspond to channels that were not ; sampled on this cycle are garbage. Zero them out and then turn on the ; full bits for the sampled channels that we just filled. andwf sample,W ; (can only include chans with new bits) iorwf full,F ; Turn on full bits for sampled channels ; compute the new state variables based on the old state and the ; 'curr_input' and 'full' vectors ; Note: a stop bit is a 1, a start bit is a 0 ; Here are the transitions of the state machine: ; ; stop_exp -> wait_start ; *set rcv_ready bits ; *set frame_err bits ; wait_start -> INPUT==1 -> wait_start ; INPUT==0 -> confirm_start ; confirm_start -> INPUT==1 -> wait_start ; INPUT==0 -> ignore1 ; ignore1 -> ignore2 ; ignore2 -> FULL==0 -> sample ; FULL==1 -> stop_exp ; *clear full bits ; sample -> ignore1 ; *set overrun error bits ; *store data bits ; *set full bits ; Turning this around into math to compute the new values of the state ; bit vectors and 'full', 'rcv_ready', 'overrun_err' and 'frame_err' vectors ; based on the old state bit vectors and the 'input' and 'full' vectors ; we get: ; ; NOTE: These comments are written assuming all the assignments happen ; simultaneously: ; ; confirm_start <- (wait_start & ~input) ; ignore1 <- (confirm_start & ~input) | sample ; ignore2 <- ignore1 ; sample <- (ignore2 & ~full) ; stop_exp <- (ignore2 & full) ; full <- full & ~ignore2 ; wait_start <- stop_exp ; | (wait_start & input) ; | (confirm_start & input) ; rcv_ready <- rcv_ready | stop_exp ; frame_err <- frame_err | (stop_exp & ~input) ; overrun_err <- overrun_err | (sample & rcv_ready) ; new_wait_start = ((wait_start | confirm_start) & input) | stop_exp movf wait_start,W iorwf confirm_start,W andwf curr_input,W iorwf stop_exp,W movwf new_wait_start ; new_ignore1 = (confirm_start & ~input) | sample comf curr_input,W andwf confirm_start,W iorwf sample,W movwf new_ignore1 ; overrun_err |= sample & rcv_ready movf sample,W andwf rcv_ready,W iorwf overrun_err,F ; sample = ignore2 & ~full comf full,W andwf ignore2,W movwf sample ; rcv_ready |= stop_exp movf stop_exp,W iorwf rcv_ready,F ; frame_err |= stop_exp & ~input comf curr_input,W andwf stop_exp,W iorwf frame_err,F ; stop_exp = ignore2 & full movf ignore2,W andwf full,W movwf stop_exp ; full = full & ~ignore2 comf ignore2,W andwf full,F ; ignore2 = ignore1 movf ignore1,W movwf ignore2 ; confirm_start = wait_start & ~input comf curr_input,W andwf wait_start,W movwf confirm_start ; wait_start = new_wait_start movf new_wait_start,W movwf wait_start ; ignore1 = new_ignore1 movf new_ignore1,W movwf ignore1 ; WIM: MASK OUT UNWANTED CHANNELS movf SerialMask,W andwf rcv_ready,F ; All Done retfie FAST ; BaudTable contasins the TMR2 Period and Scaling used for the ; selected baudrate. The interrupt rate is three times the baudrate ; NOTE: The value for 38K2 is specified but only works if you edit ; the code for a MAXIMUM of 4 channels, the CPU is not fast enough ; otherwise. ; The full list contains 8 entries: 300,600,1200,2400,4800,9600,19200,38400 BaudTable db b'01110000', .184 ; 300Bd = 900Hz (11111.8) ; 1:60 = 901Hz (11100) (+.10%) db b'01001001', .138 ; 600Bd = 1800Hz ( 5555.6) ; 1:40 = 1798Hz ( 5560) (-.08%) db b'01110000', .184 ; 1200Bd = 3600Hz ( 2777.8) ; 1:15 = 3603Hz ( 2775) (+.10%) db b'01001000', .138 ; 2400Bd = 7200Hz ( 1388.9) ; 1:10 = 7194Hz ( 1390) (-.07%) db b'00010000', .230 ; 4800Bd = 14400Hz ( 694.4) ; 1:3 = 14430Hz ( 693) (+.21%) db b'00001000', .173 ; 9600Bd = 28800Hz ( 347.2) ; 1:2 = 28736Hz ( 348) (-.22%) db b'00000000', .173 ; 192002Bd = 57600Hz ( 173.6) ; 1:1 = 57471Hz ( 174) (-.22%) db b'00000000', .86 ; 38400Bd = 115200Hz ( 86.8) ; 1:1 = 114943Hz ( 87) (-.22%) BaudTable_End IF ( (BaudTable & 0x0FF) >= (BaudTable_End & 0x0FF) ) MESSG "Warning - User Definded: Table 'BaudTable' crosses page boundary" ENDIF #define StopSerial StopSampling ; Same code as Logic Analyser ; ---------------------------------------------------------------------------- ; Start Serial monitoring ; Load TMR2 with the proper values for the selected baudrate, ; init the uart stuff and enable interrupts ; ---------------------------------------------------------------------------- StartSerial bsf ActivityLed ; Turn activity led on LFSR 0,CHDATA ; FSR0 -> Ringbuffer (extr. ptr) LFSR 1,CHDATA ; FSR1 -> Ringbuffer (ins. ptr) bcf RB_OVRRUN ; Clear overrun flag movlw 0x80 ; Init software uarts movwf rsr_chan+0 movwf rsr_chan+1 movwf rsr_chan+2 movwf rsr_chan+3 movwf rsr_chan+4 movwf rsr_chan+5 movwf rsr_chan+6 movwf rsr_chan+7 clrf rcv_ready clrf frame_err clrf full movlw 0xFF movwf wait_start clrf confirm_start clrf ignore1 clrf ignore2 clrf sample clrf stop_exp movlw .15 ; Select nonexisting channel movwf LastChannel ; as current to force control byte clrf TBLPTRU ; TBLPTR -> Timingpars movlw high BaudTable ; To be loaded in TMR2 movwf TBLPTRH movlw low BaudTable movwf TBLPTRL rlncf SerialSpeedIdx,W;Two entries per baudrate andlw 0x0E addwf TBLPTRL,F ; Now points to selected values clrf T2CON ; Stop Timer2, Prescaler = 1:1, Postscaler = 1:1 clrf TMR2 ; Clear Timer2 register clrf INTCON ; Disable interrupts clrf PIE1 ; Disable peripheral interrupts clrf PIR1 ; Clear peripheral interrupts Flags bsf IPR1,TMR2IP ; Assign high priority interrupt tblrd*+ ; Get Pre- and PostScaler values movf TABLAT,W movwf T2CON ; Set Scaling tblrd*+ ; Get Period value movf TABLAT,W movwf PR2 ; Set Period bsf PIE1,TMR2IE ; Timer 2 interrupt on bsf INTCON,PEIE ; Pheriperal interrupts enabled bsf INTCON,GIE ; Global interrupts enabled bsf T2CON, TMR2ON ; Timer2 starts to increment ; Rollover in DoSerial ; ---------------------------------------------------------------------------- ; DoSerial: Processes the serial data ; NOTE: This loop should execute in 4/3 bittime otherwise overruns ; may occur. Only critical in 19K2 setting otherwise always fast enough ; ---------------------------------------------------------------------------- DoSerial: btfss PIR1,RCIF ; Character in receiver buffer ? bra CheckSerialIO ; No movf RCREG,W ; Get character xorlw '9' ; Check for '9' (stops sampling) bnz CheckSerialIO ; No call StopSerial ; YES, stop interrupts movlw '9' call SendChar goto IDLE ; and await next command CheckSerialIO btfsc rcv_ready,0 ; Now poll all 8 channels rcall rcv_0 btfsc rcv_ready,1 rcall rcv_1 btfsc rcv_ready,2 rcall rcv_2 btfsc rcv_ready,3 rcall rcv_3 btfsc rcv_ready,4 rcall rcv_4 btfsc rcv_ready,5 rcall rcv_5 btfsc rcv_ready,6 rcall rcv_6 btfsc rcv_ready,7 rcall rcv_7 btfsc RTSline ; Request to send should be low bra DoSerial ; No, check incoming datalines btfss PIR1,TXIF ; is TXREG empty ? bra DoSerial ; No, check incoming datalines movf FSR1L,W ; Data available in ringbuffer ? subwf FSR0L,W ; subtract extract-insert pointer bz CheckOverrunSM ; No data in buffer, Do Error Check movf INDF0,W ; Get data to transmit movwf TXREG ; And do it incf FSR0L,F ; auto wrap at 256 bytes bra DoSerial CheckOverrunSM btfss RB_OVRRUN ; RingBuffer overrun detected bra DoSerial ; No, continue sampling ; FOR NOW: NO FLUSHING OF BUFFER ; AS IN L.A. MODE, JUST QUIT movlw 0xFF ; YES call SendChar ; Send Abort character goto IDLE ; and switch to IDLE ; Process the received data, each input byte results in 2 output byte: ; a Channel & Status identifier followed by the actual data byte rcvchan MACRO chan rcv_#v(chan): btfsc frame_err,chan bra ferr_#v(chan) btfsc overrun_err,chan bra oerr_#v(chan) movlw chan ; Valid char on channel 'chan' xorwf LastChannel,W ; Is this the same as last time ? bz _ic#v(chan) ; YES, no need for control byte movlw chan ; Reload channel # movwf LastChannel ; And set as current iorlw 0x80 ; Indicate channel switch rcall PutTXQueue ; and place in queue _ic#v(chan) movf rsr_chan+chan,W ; Get char rcall PutTXQueue ; and place in queue bcf rcv_ready,chan movlw 0x80 movwf rsr_chan+chan return ferr_#v(chan): ; Deal with framing error condition bcf frame_err,chan bcf rcv_ready,chan movlw chan ; Get channel number movwf LastChannel ; Tag as current iorlw 0xC0 ; and signal "Framing Error" rcall PutTXQueue movlw 0x80 movwf rsr_chan+chan return oerr_#v(chan): ; Deal with overrun condition bcf overrun_err,chan bcf rcv_ready,chan movlw chan ; Get channel number movwf LastChannel ; Tag as current iorlw 0xA0 ; and signal "Overrun Error" rcall PutTXQueue movlw 0x80 movwf rsr_chan+chan return endm rcvchan 0 rcvchan 1 rcvchan 2 rcvchan 3 rcvchan 4 rcvchan 5 rcvchan 6 rcvchan 7 ; ---------------------------------------------------------------------------- ; PutTXQueue places data to be sent te host in a 256byte circular FIFO ; To indicate the source of the data CONTROL BYTES are inserted in the ; stream. Control bytes have the 8th bit set to distinguish them from ; data bytes. If the databyte has the 8th bit set is is always preceded ; by a control byte indicating bit8 should be high. ; ; CONTROL BYTE bit7 = 1 ; bit6 = if '1' a Framing error occured on chan # ; bit5 = if '1' an Overrun error occured on chan # ; bit4 = Always 0 ; bit3 = if '1' the next databyte has the MSB set ; bit2,1,0= Channel # (0..7) ; ; DATA BYTE bit7 = 0 ; bit6..0 = 7 least signicant bits of character. ; The most signicant bit is 0 unless this byte ; is preceded with a control byte with bit3 set ; ; Sending of data with the 8bit set duplicates the amount of data which ; is send to the host!! ; ; If the Control byte equals 0xFF the internal buffer has overflown ; and the monitoring is aborted. (The main loop inserts this character, ; this routines just signals the situation, stops incoming interrupts ; and raises the RB_OVRRUN flag ; ---------------------------------------------------------------------------- PutTXQueue: movwf INDF1 ; Place character in ringbuffer incf FSR1L,F ; increment, auto rollover at 256 movf FSR0L,W ; compare with extraction ptr cpfseq FSR1L,W ; check for buffer full return ; Internal ringbuffer full, call StopSerial ; Disable ints decf FSR1L,F ; free last entry again, bsf RB_OVRRUN ; allows flushing of buffer return ; ---------------------------------------------------------------------------- ; GetSerialPars: receive 2 additional chars: ; 1) Serial Mask to use (enable/disable channels) ; 2) Speed Index (0=300,1=600,2=1200,3=2400,4=4800,5=9600,6=19200,7=38400) ; Both characters should be received within the timeout period (in order ; to prevent a hangup in this routine) ; ---------------------------------------------------------------------------- GetSerialPars lfsr 1,SerialMask ; FSR1 to start of data to get movlw 2 ; 2 bytes expected call GetCmdData btfss STATUS,C ; Carry clear: data rcvd OK goto IDLE movlw 3 ; Default 2 datalines movwf SerialMask movlw 4 ; At 4800 Baud movwf SerialSpeedIdx goto IDLE END