User Tools

Site Tools


base:spectrometer

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

base:spectrometer [2017-02-15 17:05] (current)
trap_bonzai created
Line 1: Line 1:
 +This is the code from T.P.C.T.S. demo that calculates the index values for the spectrometer. There are a few tricks in there, but I am sure many people could have written a more optimized version.
  
 +I hope it will help you understand how I did it.
 +
 +Code can be compiled using KickAss.
 +
 +/Trap
 +
 +
 +<​code>​
 +.const SID_Ghostbytes = $40                                     // Location of SID Ghostbytes (16 bytes)
 +
 +/////////////////////////////////////////////////////////////////////////////////​
 +// Spectrometer
 +/////////////////////////////////////////////////////////////////////////////////​
 +
 +Spectrometer: ​              // Call this every frame. You can then use the values in the dBMeterValue table as index for drawing your spectrometer bands.
 +
 +DecreaseBarIndexes: ​        ldx #16                             // MeterTemp contains the index values, or height, of each of the 16 bands.
 +!:                          lda MeterTemp,​x ​                    // This code will go through each of these values and decrease them until = 0.
 +                            beq dBMeterUpdate_NoDec ​   ​
 +                            dec MeterTemp,x
 +dBMeterUpdate_NoDec: ​       tay
 +                            lda SoundbarSine,​y ​                 // The index value from MeterTemp is used to get a value from a bouncing sinewave.
 +                            sta dBMeterValue,​x ​                 // SoundbarSine is the sine, it contains a 90 degree drop and a small 180 degree bounce.
 +                            dex
 +                            bpl !-
 +
 +                            ldx SID_Ghostbytes ​                 // Get Channel 1 Note
 +                            lda SID_Ghostbytes+1
 +                            jsr GetNote
 +                            lda SID_Ghostbytes+6 ​               // Isolate sustain value
 +                            and #$f0
 +                            lsr
 +                            lsr
 +                            lsr
 +                            lsr
 +                            clc
 +                            adc #6
 +                            sta MeterTemp,​x ​                    // Store new index for band representing the node played. X was received by GetNote function.
 +                            jsr CalculateSurroundings ​          // Calculate polarization of neighbouring bands
 +
 +                            ldx SID_Ghostbytes+7 ​               // Channel 2 Note
 +                            lda SID_Ghostbytes+8
 +                            jsr GetNote
 +                            lda SID_Ghostbytes+$d ​              // Repeat channel 2
 +                            and #$f0
 +                            lsr
 +                            lsr           
 +                            lsr           
 +                            lsr
 +                            clc
 +                            adc #6
 +                            sta MeterTemp,x
 +                            jsr CalculateSurroundings
 +
 +                            ldx SID_Ghostbytes+$e ​              // Repeat channel 3
 +                            lda SID_Ghostbytes+$f
 +                            jsr GetNote
 +                            lda SID_Ghostbytes+$14
 +                            and #$f0
 +                            lsr
 +                            lsr           
 +                            lsr           
 +                            lsr
 +                            clc
 +                            adc #6
 +                            sta MeterTemp,x
 +                            jsr CalculateSurroundings
 +                            rts
 +
 +GetNote: ​                   stx NoteLo ​                 // Input is the node frequency
 +                            sta NoteHi ​                 // We'll search the shortened frequency tables to approximate the node playing on a linear scale
 +                            ldx #8
 +                            ldy #0                      // Search iteration counter
 +IterateBinarySearch: ​       lda FreqTableLookupHilsb,​x  ​
 +                            sta CompareHi+1
 +                            lda FreqTableLookupHimsb,​x
 +                            sta CompareHi+2
 +                            lda FreqTableLookupLolsb,​x
 +                            sta CompareLo+1
 +                            lda FreqTableLookupLomsb,​x
 +                            sta CompareLo+2
 +
 +                            lda NoteHi ​                 // compare high bytes
 +CompareHi: ​                 cmp FreqTablePalHi
 +                            bcc Lower1 ​                 // if NUM1H < NUM2H then NUM1 < NUM2
 +                            bne Higher1 ​                // if NUM1H <> NUM2H then NUM1 > NUM2 (so NUM1 >= NUM2)
 +                            lda NoteLo ​                 // compare low bytes
 +CompareLo: ​                 cmp FreqTablePalLo
 +                            bcs Higher1 ​                // if NUM1L >= NUM2L then NUM1 >= NUM2
 +                            rts
 +
 +Lower1: ​                    txa
 +                            sec
 +                            sbc Delta,y
 +                            tax                         
 +                            iny 
 +                            cpy #4                      // Control max number of iterations
 +                            beq Done
 +                            jmp IterateBinarySearch ​    
 +
 +Higher1: ​                   txa
 +                            clc
 +                            adc Delta,y
 +                            tax
 +                            iny
 +                            cpy #4
 +                            beq Done
 +                            jmp IterateBinarySearch ​    
 +
 +Done:                       ​rts ​                        // X register contains the node played approximated to a table of 16 positions.
 +
 +CalculateSurroundings: ​     lda MeterTemp-2,​x ​          // Rudimentary,​ but it works :)
 +                            cmp MeterTemp,​x ​            // Current band index in X.
 +                            bcc LeftIsLower ​            // Take Current band from index-2 and calculate the value between these two and use it for band index-1.
 +                            lda MeterTemp-2,​x ​          // Do the same for the other side, index1=index2+((index-index2)/​2)
 +                            sec
 +                            sbc MeterTemp,x
 +                            lsr
 +                            clc
 +                            adc MeterTemp,x
 +                            sta MeterTemp-1,​x
 +                            jmp LeftSurround
 +LeftIsLower: ​               lda MeterTemp,x
 +                            sec
 +                            sbc MeterTemp-2,​x
 +                            lsr
 +                            clc
 +                            adc MeterTemp-2,​x
 +LeftSurround: ​              cmp #21
 +                            bcc !+
 +                            lda #21
 +!:                          sta MeterTemp-1,​x
 +
 +                            lda MeterTemp+2,​x
 +                            cmp MeterTemp,x
 +                            bcc LeftIsLower2
 +                            lda MeterTemp+2,​x
 +                            sec
 +                            sbc MeterTemp,x
 +                            lsr
 +                            clc
 +                            adc MeterTemp,x
 +                            sta MeterTemp+1,​x
 +                            jmp LeftSurround2
 +LeftIsLower2: ​              lda MeterTemp,x
 +                            sec
 +                            sbc MeterTemp+2,​x
 +                            lsr
 +                            clc
 +                            adc MeterTemp+2,​x
 +LeftSurround2: ​             cmp #21
 +                            bcc !+
 +                            lda #21
 +!:                          sta MeterTemp+1,​x
 +                            rts
 +
 +
 +FreqTableLookupHilsb: ​      ​.for(var i=0; i<16; i++) {          // SID Frequency lsb/msb lookup tables
 +                                   .byte <​FreqTablePalHi+(i*6)
 +                            }
 +FreqTableLookupHimsb: ​      ​.for(var i=0; i<16; i++) {
 +                                   .byte >​FreqTablePalHi+(i*6)
 +                            }
 +FreqTableLookupLolsb: ​      ​.for(var i=0; i<16; i++) {
 +                                   .byte <​FreqTablePalLo+(i*6)
 +                            }
 +FreqTableLookupLomsb: ​      ​.for(var i=0; i<16; i++) {
 +                                   .byte >​FreqTablePalLo+(i*6)
 +                            }
 +
 +temp:                       .byte 0
 +NoteLo: ​                    .byte 0
 +NoteHi: ​                    .byte 0
 +Delta: ​                     .byte 4,2,1,0
 +
 +FreqTablePalLo:​
 +                            .byte $17,​$27,​$39,​$4b,​$5f,​$74,​$8a,​$a1,​$ba,​$d4,​$f0,​$0e ​ // Shortened frequency table, because I don't need full granularity.
 +                            .byte $2d,​$4e,​$71,​$96,​$be,​$e8,​$14,​$43,​$74,​$a9,​$e1,​$1c ​ // 2
 +                            .byte $5a,​$9c,​$e2,​$2d,​$7c,​$cf,​$28,​$85,​$e8,​$52,​$c1,​$37 ​ // 3
 +                            .byte $b4,​$39,​$c5,​$5a,​$f7,​$9e,​$4f,​$0a,​$d1,​$a3,​$82,​$6e ​ // 4
 +                            .byte $68,​$71,​$8a,​$b3,​$ee,​$3c,​$9e,​$15,​$a2,​$46,​$04,​$dc ​ // 5
 +                            .byte $d0,​$e2,​$14,​$67,​$dd,​$79,​$3c,​$29,​$44,​$8d,​$08,​$b8 ​ // 6
 +                            .byte $a1,​$c5,​$28,​$cd,​$ba,​$f1,​$78,​$53,​$87,​$1a,​$10,​$71 ​ // 7
 +                            .byte $42,​$89,​$4f,​$9b,​$74,​$e2,​$f0,​$a6,​$0e,​$33,​$20,​$ff ​ // 8
 +FreqTablePalHi:​
 +                            .byte $01,​$01,​$01,​$01,​$01,​$01,​$01,​$01,​$01,​$01,​$01,​$02 ​ // 1
 +                            .byte $02,​$02,​$02,​$02,​$02,​$02,​$03,​$03,​$03,​$03,​$03,​$04 ​ // 2
 +                            .byte $04,​$04,​$04,​$05,​$05,​$05,​$06,​$06,​$06,​$07,​$07,​$08 ​ // 3
 +                            .byte $08,​$09,​$09,​$0a,​$0a,​$0b,​$0c,​$0d,​$0d,​$0e,​$0f,​$10 ​ // 4
 +                            .byte $11,​$12,​$13,​$14,​$15,​$17,​$18,​$1a,​$1b,​$1d,​$1f,​$20 ​ // 5
 +                            .byte $22,​$24,​$27,​$29,​$2b,​$2e,​$31,​$34,​$37,​$3a,​$3e,​$41 ​ // 6
 +                            .byte $45,​$49,​$4e,​$52,​$57,​$5c,​$62,​$68,​$6e,​$75,​$7c,​$83 ​ // 7
 +                            .byte $8b,​$93,​$9c,​$a5,​$af,​$b9,​$c4,​$d0,​$dd,​$ea,​$f8,​$ff ​ // 8
 +
 +                            .byte 0,0
 +dBMeterValue: ​              .fill 16,0
 +                            .byte 0,0
 +MeterTemp: ​                 .fill 16,0
 +                            .byte 0,0
 +               
 +                            // Quick'​n'​dirty 180degree + 90degree drop sine.
 +SoundbarSine: ​              .byte 0,​2,​4,​5,​6,​6,​5,​4,​2,​0,​2,​4,​6,​8,​9,​10,​11,​12,​13,​14,​14,​15
 +
 +///////////////////////////////////////////////////////////////////////////////////////////​
 +// Play music using ghostbytes
 +///////////////////////////////////////////////////////////////////////////////////////////​
 +PlayMusic: ​                 lda $01                             // Grab SID data. This is called from IRQ.
 +                            pha
 +                            lda #$30
 +                            sta $01
 +                            jsr $1003
 +                            ldx #$19
 +!CopySIDData: ​              lda $d400,x
 +                            sta SID_Ghostbytes,​x
 +                            dex
 +                            bpl !CopySIDData-
 +                            pla 
 +                            sta $01
 +                            ldx #$19
 +!CopyToSID: ​                lda SID_Ghostbytes,​x
 +                            sta $d400,x
 +                            dex
 +                            bpl !CopyToSID-
 +                            rts
 +</​code>​
base/spectrometer.txt ยท Last modified: 2017-02-15 17:05 by trap_bonzai