;-----------------------------------------------------------------------------------------------; ; Program: Lights ; ; Developed by David J. Brown ; ; Copyright (c) April 13, 2004 David J. Brown ; ; Email: davebr@earthlink.net ; ; Web site: http://modularsynthesis.com ; ;-----------------------------------------------------------------------------------------------; ; LICENSE AGREEMENT: ; ; This program is free software. You can redistribute it and/or modify it. ; ; ; ; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, ; ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ; ;-----------------------------------------------------------------------------------------------; ' ' Description: ' ' This idiotic program makes pretty patterns in the PSIM lights. ' Someday I'll make the lights follow the inputs and talk to the SpeakJet. ' ' Inputs: ' START = not used ' STOP = not used ' IN-1 = Random seed number ' IN-2 = Pattern selection: random, count, ping, shift, or flash ' IN-3 = Pattern selection repeat (1 - 32) ' IN-4 = Led brightness ' MIDI-In = not used ' ' Outputs: ' AUX = not used ' MIDI-Out= not used ' Speakjet= Voice output ' ' Written by David J. Brown ' Revision: 0.2X ' April 28, 2010 ' History: 0.2X Changed shiftout for Studio ' 0.2 Changed ping to eliminate push/pop ' 0.1 Added display of program name and mode ' 0.0 Initial release of LIGHTS program ' Date: May 12, 2004 ' '##################################################### ' ' ### CONDITIONAL COMPILING OPTION ### ' Set TIMER INTERRUPT mode ' note: Run led will blink if TM_FLAG defined ' ' Comment out next line to disable timer interrupts TM_FLAG CON 1 'Define to enable timer interrupts ' Comment to disable timer interrupts ' '##################################################### ' ' ### CONDITIONAL COMPILING OPTION ### ' Set ADC INTERRUPT mode ' note: Requires TM_FLAG to be defined ' ' Comment out next line to disable ADC interrupts ADC_FLAG CON 1 'Define to enable ADC interrupt mode ' Comment to set polled ADC mode ' '##################################################### ' 'DJB TEMPLATE written by David J. Brown 'Based on code from Brice Hornback and Grant Richter 'Revision: 0.4 ' May 11, 2004 'History: 0.4 Added averaged ADC input driver (polled or ' interrupt mode), outled display (for debug), ' SpeakJet driver, renamed program to DJB TEMPLATE ' 0.3 Added program header information, modified ' pin initialization ' 0.2 Initialize AUX output low and SpeakJet pins ' 0.1 Added DAC & led initialization, 1 mS timestamp, ' stop led blinks when MIDI data received, run ' led toggles @ 0.5 S for health indication ' 0.0 Initial release of MIDI INPUT & OUTPUT program 'Date: April 13, 2004 '***************************************************** ' Module: PSIM-1 REV1b ' Processor Type: Basic Micro - Basic Atom Pro24M '***************************************************** ' ' Basic Micro Atom Pro-24M Configuration ' ' P0 - Analog IN-1 (0-5 VDC) ' P1 - Analog IN-2 (0-5 VDC) ' P2 - Analog IN-3 (0-5 VDC) ' P3 - Analog IN-4 (0-5 VDC) ' P4 - START button (momentary normally open switch) ' P5 - STOP button (momentary normally open switch) ' P6 - I2C/SDA (Reserved) - J3 Pin 2 (SpeakJet buffer half full) ' P7 - I2C/SDL (Reserved) - J3 Pin 1 (Serial data to SpeakJet) ' P8 - AUX digital I/O ' P9 - STOP LED ' P10 - RUN LED ' P11 - DAC - LOADDACS ' P12 - DAC - SERDATA ' P13 - DAC - CLOCK ' P14 - RXD (reserved) - J5 Pin 1 (MIDI-In) ' P15 - TXD (reserved) - J5 Pin 2 (MIDI-Out) ' '***************************************************** ' 'Defined Variables ADC1 CON 0 'IN-1 jack ADC2 CON 1 'IN-2 jack ADC3 CON 2 'IN-3 jack ADC4 CON 3 'IN-4 jack BSTART CON 4 'Start button and jack BSTOP CON 5 'Stop button and jack AUX CON 8 'AUX jack STOPLED CON 9 'Stop led (red) RUNLED CON 10 'Run led (green) LOADDACS CON 11 'Load DAC SERDATA CON 12 'Serial data to DAC (16-bit) CLOCK CON 13 'Clock DAC ' RAWDAC1 VAR WORD 'Temporary variable: LOADALLDACS RAWDAC2 VAR WORD 'Temporary variable: LOADALLDACS RAWDAC3 VAR WORD 'Temporary variable: LOADALLDACS RAWDAC4 VAR WORD 'Temporary variable: LOADALLDACS DAC1V VAR WORD 'DAC value sent to OUT-1 jack: LOADALLDACS DAC2V VAR WORD 'DAC value sent to OUT-2 jack: LOADALLDACS DAC3V VAR WORD 'DAC value sent to OUT-3 jack: LOADALLDACS DAC4V VAR WORD 'DAC value sent to OUT-4 jack: LOADALLDACS ' ADC1V VAR WORD 'IN-1 ADC value: CALCTIME ADC2V VAR WORD 'IN-2 ADC value: CALCTIME ADC3V VAR WORD 'IN-3 ADC value: CALCTIME ADC4V VAR WORD 'IN-4 ADC value: CALCTIME ' ADC1P VAR BYTE 'ADC1 buffer pointer: TM_ISR, SCANADCA #IFDEF ADC_FLAG ADC2P VAR BYTE 'ADC2 buffer pointer: TM_ISR ADC3P VAR BYTE 'ADC3 buffer pointer: TM_ISR ADC4P VAR BYTE 'ADC4 buffer pointer: TM_ISR ISR_CNT VAR NIB 'Timer pass counter: TM_ISR #ENDIF ADC1T VAR LONG 'ADC1 temporary variable: TM_ISR, SCANADCA ADC2T VAR LONG 'ADC2 temporary variable: TM_ISR, SCANADCA ADC3T VAR LONG 'ADC3 temporary variable: TM_ISR, SCANADCA ADC4T VAR LONG 'ADC4 temporary variable: TM_ISR, SCANADCA ADC1B VAR LONG(2) 'ADC1 last 4 samples buffer: TM_ISR, SCANADCA ADC2B VAR LONG(2) 'ADC2 last 4 samples buffer: TM_ISR, SCANADCA ADC3B VAR LONG(2) 'ADC3 last 4 samples buffer: TM_ISR, SCANADCA ADC4B VAR LONG(2) 'ADC4 last 4 samples buffer: TM_ISR, SCANADCA ' LEDDATA VAR BYTE 'Variable to display: OUTLED SPKDATA VAR BYTE 'Variable to send to SpeakJet: SPEAKJET LOOPCTR VAR BYTE 'Loop counter RNDCTR VAR WORD 'Random Seed TEMPB VAR BYTE 'Temp byte ' '***************************************************** ' 'Initialize PSIM pins DIRS=%0011111000000000 'Configure pin direction (1=output, 0=input) ' note: backwards from Atom ' Inputs: ' MIDI-In, AUX, SpeakJet flow control, ' Start, Stop, IN-4, IN-3, IN-2, IN-1 ' Outputs: ' MIDI-Out, LOADDACS, SERDATA, CLOCK, ' stop led, run led LOW RUNLED 'Set run led off LOW STOPLED 'Set stop led off HIGH LOADDACS 'Set DAC load-0 high LOW SERDATA 'Set DAC data low LOW CLOCK 'Set DAC clock low ' #IFDEF TM_FLAG 'Setup timerw for 1 millisecond interupts LET TMRW=%10001000 'Set Timer Mode Register to enable count LET TCRW=%10110000 'Set Timer Control Register ' TCNT cleared by compare match ' /8 internal clock LET TIERW=%01110000 'Set Timer Interrupt register to disable overflow interrupt LET TSRW=%01110000 'Set Timer Status Register to default LET TIOR0=%10001000 'Set Timer I/O Regiseter 0 to default LET TIOR1=%10001000 'Set Timer I/O Register 1 to default LET GRA=2000 'Set General Register A ' 16 MHz clock /8 = 2 MHz ' 2000 counts = 1 mS interrupt #ENDIF ' 'Initialize variables LET ADC1P=0 'Set ADC1 pointer to 0 #IFDEF ADC_FLAG LET ADC2P=0 'Set ADC2 pointer to 0 LET ADC3P=0 'Set ADC3 pointer to 0 LET ADC4P=0 'Set ADC4 pointer to 0 LET ISR_CNT=0 'Initialize ISR pass counter to 0 #ENDIF LET ADC1B(0)=0 'Initialize ADC1 buffer data to 0 LET ADC1B(1)=0 LET ADC2B(0)=0 'Initialize ADC2 buffer data to 0 LET ADC2B(1)=0 LET ADC3B(0)=0 'Initialize ADC3 buffer data to 0 LET ADC3B(1)=0 LET ADC4B(0)=0 'Initialize ADC4 buffer data to 0 LET ADC4B(1)=0 ' #IFDEF TM_FLAG ONINTERRUPT TIMERWINT_IMIEA, TM_ISR ENABLE TIMERWINT_IMIEA 'Enable timer interrupt #ENDIF ' PAUSE 100 LET RNDCTR=ADC1V|$80 'Semi-random seed from IN-1 ' 'Display program name ENABLEHSERIAL SETHSERIAL H31200,H8DATABITS,HNOPARITY,H1STOPBITS HSEROUT [$f0,$7d,$0a,$18,"Lights",$f7] 'Clear display, overwrite, program name ' 'Lights starts here MAIN: HSEROUT [$f0,$7d,$0b,$18,"1 Bounce",$f7] 'home2 & mode FOR LOOPCTR=1 TO 10 'Shift right then left GOSUB CYCLEONE NEXT HSEROUT [$f0,$7d,$0b,$18,"2 Flash ",$f7] 'home2 & mode FOR LOOPCTR=1 TO 15 'Flash GOSUB FLASH NEXT HSEROUT [$f0,$7d,$0b,$18,"3 Random",$f7] 'home2 & mode FOR LOOPCTR=1 TO 30 'Random GOSUB RFLASH NEXT HSEROUT [$f0,$7d,$0b,$18,"4 Count ",$f7] 'home2 & mode GOSUB COUNTIT 'Count up & down HSEROUT [$f0,$7d,$0b,$18,"5 Ping ",$f7] 'home2 & mode FOR LOOPCTR=1 TO 20 'Ping back and forth GOSUB PING NEXT FOR LOOPCTR=1 TO (ADC3V/32)+1 'Max of 32 cycles GOSUB PICKIT 'Pick a pattern from IN-2 NEXT GOTO MAIN ' '***************************************************** ' SUBROUTINES '***************************************************** ' 'Pick-a-pattern PICKIT: IF ADC2V > 410 THEN '4+ volts random HSEROUT [$f0,$7d,$0b,$18,"6 Random",$f7] 'home2 & mode GOTO RFLASH ELSEIF ADC2V > 308 '3 to 4 volts count HSEROUT [$f0,$7d,$0b,$18,"6 Count ",$f7] 'home2 & mode GOTO COUNTIT ELSEIF ADC2V > 204 '2 to 3 volts ping HSEROUT [$f0,$7d,$0b,$18,"6 Bounce",$f7] 'home2 & mode GOTO PING ELSEIF ADC2V > 102 '1 to 2 volts shift left and right HSEROUT [$f0,$7d,$0b,$18,"6 Ping ",$f7] 'home2 & mode GOTO CYCLEONE ELSE HSEROUT [$f0,$7d,$0b,$18,"6 Flash ",$f7] 'home2 & mode GOTO FLASH '0 to 1 volt flash ENDIF ' 'Shift lights right then left CYCLEONE: LET LEDDATA=01 RIGHT: GOSUB LOADLIGHTS IF LEDDATA=32 THEN LEFT 'Shift right until bit5 LEDDATA=LEDDATA*2 PAUSE 75 GOTO RIGHT LEFT: GOSUB LOADLIGHTS IF LEDDATA=01 THEN DONE 'Shift left until bit0 LEDDATA=LEDDATA/2 PAUSE 75 GOTO LEFT DONE: RETURN ' 'Flash lights on & off FLASH: LET LEDDATA=63 'All on GOSUB LOADLIGHTS PAUSE 100 LET LEDDATA=0 'All off GOSUB LOADLIGHTS PAUSE 100 RETURN ' 'Flash random RFLASH: LET RNDCTR=RANDOM(RNDCTR) LET LEDDATA=RNDCTR&$003F 'Keep to bits 0 - 5 GOSUB LOADLIGHTS PAUSE 125 RETURN ' 'Count up and down COUNTIT: FOR LOOPCTR=63 TO 1 STEP -1 'Count up backwards LEDDATA=LOOPCTR GOSUB LOADLIGHTS PAUSE 10 NEXT FOR LOOPCTR=1 TO 63 'Count down backwards LEDDATA=LOOPCTR GOSUB LOADLIGHTS PAUSE 10 NEXT RETURN ' 'Ping back and forth PINGD BYTETABLE 01,32,02,16,04,08,04,16,02,32 PING: LET TEMPB=LOOPCTR FOR LOOPCTR=0 TO 9 LET LEDDATA=PINGD(LOOPCTR) 'Ping data pattern GOSUB LOADLIGHTS PAUSE 100 NEXT LET LOOPCTR=TEMPB RETURN ' 'Output LEDDATA to lights LOADLIGHTS: LET RAWDAC1=(LEDDATA.BIT0*ADC4V*4)+49152 LET RAWDAC2=(LEDDATA.BIT1*ADC4V*4)+32768 LET RAWDAC3=(LEDDATA.BIT2*ADC4V*4)+16384 LET RAWDAC4=LEDDATA.BIT3*ADC4V*4 'Shift out 16 bits mode 4 SHIFTOUT SERDATA,CLOCK,FASTMSBPRE,[RAWDAC1\16] PULSOUT LOADDACS,1 'Pulse loaddacs for each channel SHIFTOUT SERDATA,CLOCK,FASTMSBPRE,[RAWDAC2\16] PULSOUT LOADDACS,1 SHIFTOUT SERDATA,CLOCK,FASTMSBPRE,[RAWDAC3\16] PULSOUT LOADDACS,1 SHIFTOUT SERDATA,CLOCK,FASTMSBPRE,[RAWDAC4\16] PULSOUT LOADDACS,1 OUT9=LEDDATA.BIT4 'Stop led OUT10=LEDDATA.BIT5 'Run led RETURN ' SPEAKJET: RETURN ' #IFDEF ADC_FLAG 'Scan and average IN-1 to IN-4 'ADCxV is input averaged over last 4 samples (0 - 1023) 'ADCxB(0) & ADCxB(1) are last 4 word samples '600 uS execution time 'Written by David J. Brown SCANADCA: ADIN ADC1, ADC1B.WORD1(ADC1P) 'Get IN-1 into buffer LET ADC1T=ADC1B(0)+ADC1B(1) 'Add two high words together and low words together LET ADC1V=(ADC1T.WORD1+ADC1T.WORD0)/4 ADIN ADC2, ADC2B.WORD1(ADC1P) 'Get IN-2 into buffer LET ADC2T=ADC2B(0)+ADC2B(1) 'Add two high words together and low words together LET ADC2V=(ADC2T.WORD1+ADC2T.WORD0)/4 ADIN ADC3, ADC3B.WORD1(ADC1P) 'Get IN-3 into buffer LET ADC3T=ADC3B(0)+ADC3B(1) 'Add two high words together and low words together LET ADC3V=(ADC3T.WORD1+ADC3T.WORD0)/4 ADIN ADC4, ADC4B.WORD1(ADC1P) 'Get IN-4 into buffer LET ADC4T=ADC4B(0)+ADC4B(1) 'Add two high words together and low words together LET ADC4V=(ADC4T.WORD1+ADC4T.WORD0)/4 LET ADC1P=(ADC1P+1)&$03 'Increment pointer and wrap at 3 RETURN #ENDIF ' '***************************************************** 'INTERRUPT SERVICE ROUTINES '***************************************************** ' #IFDEF TM_FLAG 'Interrupt service routine for timer 'Increments TIMECOUNT value 'Turn off stop led at TURNOFF value 'Toggle run led at 512 mS intervals 'This ISR is coded for fastest execution 'Written by David J. Brown TM_ISR: #ENDIF #IFNDEF ADC_FLAG RESUME 'Resume if ADC polled mode #ENDIF #IFDEF ADC_FLAG 'Continue if ADC interrupt mode 'Sample ADC1 - ADC4 at specific intervals 'ADCXV is input averaged over last 4 samples (0 - 1023) 'ADCxB(0) & ADCxB(1) are last 4 word samples LET ISR_CNT=ISR_CNT+1 'Change the following table to modify the scan rate for each input '175 uS execution time so maximum of one sample and average per interrupt 'Currently set for: IN-1 @ 2 mS, IN-2 @ 4 mS, IN-3 @ 8 mS, IN-4 @ 8 mS BRANCH ISR_CNT, [AVG1, AVG2, AVG1, AVG3, AVG1, AVG2, AVG1, AVG4, | AVG1, AVG2, AVG1, AVG3, AVG1, AVG2, AVG1, AVG4] 'Sample IN-1 AVG1: ADIN ADC1, ADC1B.WORD1(ADC1P) 'Get IN-1 into buffer LET ADC1T=ADC1B(0)+ADC1B(1) 'Add two high words together and low words together LET ADC1V=(ADC1T.WORD1+ADC1T.WORD0)/4 LET ADC1P=(ADC1P+1)&$03 'Increment pointer and wrap at 3 RESUME 'Sample IN-2 AVG2: ADIN ADC2, ADC2B.WORD1(ADC2P) 'Get IN-2 into buffer LET ADC2T=ADC2B(0)+ADC2B(1) 'Add two high words together and low words together LET ADC2V=(ADC2T.WORD1+ADC2T.WORD0)/4 LET ADC2P=(ADC2P+1)&$03 'Increment pointer and wrap at 3 RESUME 'Sample IN-3 AVG3: ADIN ADC3, ADC3B.WORD1(ADC3P) 'Get IN-3 into buffer LET ADC3T=ADC3B(0)+ADC3B(1) 'Add two high words together and low words together LET ADC3V=(ADC3T.WORD1+ADC3T.WORD0)/4 LET ADC3P=(ADC3P+1)&$03 'Increment pointer and wrap at 3 RESUME 'Sample IN-4 AVG4: ADIN ADC4, ADC4B.WORD1(ADC4P) 'Get IN-4 into buffer LET ADC4T=ADC4B(0)+ADC4B(1) 'Add two high words together and low words together LET ADC4V=(ADC4T.WORD1+ADC4T.WORD0)/4 LET ADC4P=(ADC4P+1)&$03 'Increment pointer and wrap at 3 RESUME #ENDIF ' '***************************************************** 'END OF PROGRAM '*****************************************************