LCD VU Meter

Hola a todos,

Encontré este código en Internet, pero esto funciona solo para LED, no para LCD, entonces, ¿cómo podemos convertirlo para que funcione en LCD VU Meter?

Esperando la respuesta de tu maestro.

Lahmun,


Código:
' Stereo peak-hold/decay VU meter (2x10 or 2x16 LEDs), version 2.0
'       on-the-fly switchable mode (style) jumper

'   Filename: VU_2x16_BarJp.bas   
' Written for the Proton BASIC compiler v3.6.0.3, © Istvan K, 2017

'$define  WIDTH 10  ' 2x10-led
$define  WIDTH 16  ' 2x16-led

' peak hold time (also see below):
$define PHOLDTIME 500 ' ms, max 255*4=1020 ms (phold is a 8-bit counter)

'-----------

Device = 16F88     ' a 18-pin PIC
Declare Xtal = 8   ' int osc

' not HS_OSC but INTRC_IO, config word: 0x3F10
Config INTRC_IO, WDT_OFF, MCLR_OFF, LVP_OFF, _
PWRTE_ON, BODEN_OFF, CP_OFF, DEBUG_OFF
' intosc (8 Mhz), RA6 and RA7 (ext osc pins) are IOs, MCLR disabled (input)

' Define ADC parameters:
$if WIDTH = 10
 Declare Adin_Res = 8   ' 8-bit result
$else
 Declare Adin_Res = 10  ' have to set right justify (ADFM_bit = 1)
$endif

Declare Adin_Tad = FRC  ' RC OSC
Declare Adin_Stime = 50 ' 50us sample time

Declare Dead_Code_Remove On
Declare Reminders OFF
Declare Optimiser_Level 2

On_Hardware_Interrupt TMR2_IT ' 1 ms for exact mux timing

' IT timed led multiplexing, using four 5-led groups ('quintets')
'   If WIDTH = 16 then four 8-led groups are used (4 'octets')
' Circuit: VU_2x16_BarJp.DSN, input is a real stereo wav file.
 
' RA0, RA1, RA6, RA7 = mux outputs (ON = 0)
' RA2, RA4 = AN_R, AN_L (AN2 and AN4)
' RA3 = REF (VREF+), set by a pot, sensitivity (level)
' RA5 = MODE jumper: 0 = POINTER, 1 = BAR (standard mode)
' RB3..RB7 = L0...L4 = common 5-bit Led port (5 anodes of all quintets)
'   if WIDTH = 16 then the full 8-bit PORTB is used (RB0..7 = L0..7)

' Four pins to drive the common cathodes of the 4 groups (quintets/octets):

'  RcH 'R'ight 'c'athodes 'H'igh (group drive pin, active 0)
'  RcL                    'L'ow
'  LcH 'L'eft
'  LcL

$define RcH PORTA.0
$define RcL PORTA.7
$define LcH PORTA.1
$define LcL PORTA.6

$define LED_Port PORTB

' on-the-fly switchable mode (style) jumper (BAR_JP, open = 1: BAR mode)
' jumper closed: running led pointer, not bar (plus the lastpeak if any)
  '      open: a standard VU meter will be displayed (filled bar)
  ' ie all the LEDs on the left side of the mpeak will also turn on

$define BAR_JP PORTA.5

' different (own) variables for R and L channels:
Dim R_peak   As Byte
Dim R_phold  As Byte
Dim R_dhold  As Byte

Dim L_peak   As Byte
Dim L_phold  As Byte
Dim L_dhold  As Byte

' common variables:
Dim mpeak    As Byte ' momentary peak position
Dim lastpeak As Byte
Dim pos      As Byte
Dim barbits  As Word ' 10 bar positions > 16-bit var, leftmost pos. > bit 6
                     ' 16 bar positions > 16-bit var, leftmost pos. > bit 0

$if WIDTH = 10
 Dim adval   As Byte
 Dim LogTable[10] As Byte ' array in RAM, for speed
$else ' width = 16
 Dim adval   As Word
 Dim LogTable[16] As Word
$endif

Symbol TMR2_ON T2CON.2

'GoTo main
' CMCON = 7 (comparators OFF, automatically placed by the compiler)
'main:

' HW init
  OSCCON = %01110000        ' Internal clock at 8 MHz
  ANSEL  = %00011100        ' set RA2, RA3 (VREF+) and RA4 as analog input
  Repeat Until OSCCON.2 = 1 ' IOFS bit, wait until INTOSC frequency stable

  TRISA = %00111100         ' mux pins are outputs
  TRISB = 0 ' tris reg of LED_Port (PORTB), all outputs

  ' leds off
  PORTA = 0xFF ' all mux pins are off (1)
  LED_Port = 0

  ADCON1.5 = 1 ' VCFG1 = 1 (use RA3 as VREF+), it remains 1

$if WIDTH = 16' only for 10-bit AD:
  ADCON1.7 = 1 ' ADFM = 1: right justified (missing in Proton ADin)
$endif

'   init timer2 for mux timing: period = 1 ms
' a channel calculation is max 300 us (without timer2 waiting)

' Prescaler=1:1, PostScaler=1:8, Period = 1 ms (8 MHz clock)
' 1 ms/group, the whole loop is 4 ms (250 Hz refresh rate)

  PR2 = 250           ' Timer2 Match value
  T2CON = %00111100   ' enable Timer2 with 1:8 postscaler, 1:1 prescaler
  PIR1.1 = 0          ' clear TMR2IF
  PIE1 = %10          ' only TMR2IE = 1 (enable Timer2 IT)

  INTCON = 0xC0       ' Enable global (GIE) and periferial (PEIE) ITs

'init variables:

R_peak  = 0
R_phold = 0
R_dhold = 0

L_peak  = 0
L_phold = 0
L_dhold = 0

$if WIDTH = 10
    ' 10-stage log table in RAM, 6 then 3 dB/step, can be modified :-)
'  2,  4,  8,  16, 32, 64, 90, 128, 180, 255
' -36 -30 -24 -18 -12  -6  -3   0   +3   +6   dB
    ' fill the table:
    LogTable[0] = 2
    LogTable[1] = 4
    LogTable[2] = 8
    LogTable[3] = 16
    LogTable[4] = 32
    LogTable[5] = 64
    LogTable[6] = 90
    LogTable[7] = 128
    LogTable[8] = 180
    LogTable[9] = 255
$else
    ' 16-stage WORD log table in RAM, 3 dB/step
' 6,  8,  11, 16, 23, 32, 45, 64, 90, 127, 180, 255, 361, 510, 721, 1020
'-39 -36 -33 -30 -27 -24 -21 -18 -15  -12  -9   -6   -3    0   +3    +6 dB
    ' fill the table:
    LogTable[0] = 6
    LogTable[1] = 8
    LogTable[2] = 11
    LogTable[3] = 16
    LogTable[4] = 23
    LogTable[5] = 32
    LogTable[6] = 45
    LogTable[7] = 64
    LogTable[8] = 90
    LogTable[9] = 127
    LogTable[10] = 180
    LogTable[11] = 255
    LogTable[12] = 361
    LogTable[13] = 510
    LogTable[14] = 721
    LogTable[15] = 1020
$endif

$define LOOPTIME 4    ' 4 ms repeating (loop) time (used below)
' 4 mS/loop (using 1 ms timer2 IT) = 250 Hz refresh rate at 8 MHz clock

  While 1=1 ' infinite loop

    adval = ADIn 2    ' sample AN2 (channel R)
    GoSub R_PosCalc   ' calculate the momentary mpeak and lastpeak
    GoSub Set_BarBits ' update barbits using mpeak and lastpeak

'   Execution time of the above three routines varies (depends on audio level)
'   but this is compensated by the timer2 waiting, so every mux step will be
'   exactly 1 ms (to get same brightness for the four led-groups).
'    The mux order is: RcH RcL LcH LcL

    Repeat Until TMR2_ON = 0 ' wait for timer2 IT (max 1 ms to timer2 off)
    TMR2_ON = 1              ' restart timer2

    LcL = 1  ' mux off (switch off the lastly switched mux pin)
    LED_Port = barbitsH ' R higher quintet/octet
    RcH = 0  ' actual (here: the first) mux pin ON

$if WIDTH = 10 ' ie not 16
    barbits = barbits >> 3 ' calculate the R lower quintet (see below)
$endif
    Repeat Until TMR2_ON = 0
    TMR2_ON = 1

    RcH = 1
    LED_Port = barbits ' R lower quintet/octet
    RcL = 0

    ' calculate mpeak, lastpeak and barbits (for channel L)
    adval = ADIn 4    ' appr 107 us
    GoSub L_PosCalc   ' max 82 us
    GoSub Set_BarBits ' 87-90 us

    Repeat Until TMR2_ON = 0
    TMR2_ON = 1

    RcL = 1
    LED_Port = barbitsH ' L higher quintet/octet
    LcH = 0

$if WIDTH = 10
    barbits = barbits >> 3
$endif
    Repeat Until TMR2_ON = 0
    TMR2_ON = 1

    LcH = 1
    LED_Port = barbits ' L lower quintet/octet
    LcL = 0

  Wend ' infinite loop

' --------------------- end of main

' subroutines:

TMR2_IT:
  Context Save ' how to disable it (in this case nothing to save) ????
   PIR1.1 = 0  ' clear TMR2IF (IT flag)
   TMR2_ON = 0 ' stop TMR2, examined (and set) in the main loop
  Context Restore

' peak hold/decay timings (in reality other values may be needed, try it!)
'   starting value of the counters, decremented once per each main loop:
$define PHOLDCNT PHOLDTIME/LOOPTIME ' countdown before the first decay
 ' = 125, ie the peak bit stays for 125*4=500 ms before decay begins
$define DHOLDCNT PHOLDCNT/13        ' countdown before the next decay
 ' = 9, ie the decay repeating time is 9*4=36 ms (for my Proteus !!)
' the above values depend on the speed of the PC so you have to try

R_PosCalc: ' input: adval, output: mpeak and lastpeak variables

  mpeak = WIDTH - 1  ' position loop in reversed order, to find mpeak
  Do
     ' comparing adc value to the actual table value
     If adval >= LogTable[mpeak] Then
        ' momentary max position (mpeak) found
        If mpeak > R_peak Then ' new, greater peak (pos 0 is excluded)
            R_peak = mpeak     ' preserve it for the next call
            ' now lastpeak will be peak, so clear prev. lastpeak if any:
            lastpeak.7 = 1     ' invalid (too large) value
            ' prepare peak hold/decay counters:
            R_phold = PHOLDCNT ' (re)start peak hold time (also preserved)
            R_dhold = 0        ' if phold is expired, this will be DHOLDCNT
            Return             ' end of function
        EndIf ' end new peak
        Break                ' exit loop
     EndIf ' end of compare
     Dec mpeak
  Loop While mpeak.7 = 0
  ' If the loop ran through, mpeak will be 0xFF (invalid value: not found)

  ' calculate peak hold and decay
  If R_phold != 0 Then
     Dec R_phold ' previous (last) peak bit (led) remains
  Else
     ' phold time is expired, repeating peak decay begins
     If R_dhold != 0 Then
        Dec R_dhold
     ElseIf R_peak != 0 Then
        ' Repeat peak decay until zero (or a new, greater peak)
        Dec R_peak ' zero peak: end of repeating decay
        R_dhold = DHOLDCNT ' re)start decay time
     EndIf
  EndIf
  ' lastpeak displayed if it is greater than mpeak (the momentary max)
  lastpeak = R_peak
  If lastpeak = 0 Then ' zero lastpeak is invalid (excluded)
     lastpeak.7 = 1    ' surely too large value
  EndIf
Return ' end of R_PosCalc


L_PosCalc: ' same as R_PosCalc but with L_ prefixes

  mpeak = WIDTH - 1
  Do
     If adval >= LogTable[mpeak] Then
        If mpeak > L_peak Then
            L_peak = mpeak
            lastpeak.7 = 1
            L_phold = PHOLDCNT
            L_dhold = 0
            Return
        EndIf
        Break
     EndIf
     Dec mpeak
  Loop While mpeak.7 = 0

  If L_phold != 0 Then
     Dec L_phold
  Else
     If L_dhold != 0 Then
        Dec L_dhold
     ElseIf L_peak != 0 Then
        Dec L_peak
        L_dhold = DHOLDCNT
     EndIf
  EndIf
  lastpeak = L_peak
  If lastpeak = 0 Then
     lastpeak.7 = 1
  EndIf
Return ' end of L_PosCalc


' Set_BarBits:
'  as the name shows, it only sets the "barbits" variable, that you
'  have to send to the appropriate PIC ports to drive the LEDs.
'   Its result:

'  ****** If WIDTH = 10:
'<   barbitsH  > <   barbits   >
'7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0    bit numbers (x = undetermined, not used)
'H H H H H L L L L L x x x x x x    H = higher quintet, L = lower quintet
' the higher quintet is ready in barbitsH (bit7-3, PORTB.2..0 are not used)

'*** after three right-shifts (barbits >> 3):
'<   barbitsH  > <   barbits   >
'7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
'0 0 0 H H H H H L L L L L x x x
' the lower quintet = barbits.7-3 (bit2..0 are not used, too)

'  ****** If WIDTH = 16:
'<   barbitsH  > <   barbits   >
'7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0    bit numbers
'H H H H H H H H L L L L L L L L    H = higher octet, L = lower octet
' both octets are ready in barbits (barbitsH, barbits)

Set_BarBits: ' input: mpeak and lastpeak, output: barbits

   pos = 0   ' position of the leftmost bar LED
             ' after 10 rshifts it will be the barbits.6
   Do        ' pos loop 0..(WIDTH-1)
      ' rshifted and barbitsH.7 = 0 which means that bit (led) is off:
      barbits = barbits >> 1

      ' compare position with the actual (valid) mpeak and lastpeak:
      If BAR_JP = 0 Then ' pointer mode (running led)
         If pos = mpeak Then set_led
      ElseIf mpeak.7 = 0 Then ' valid mpeak 
         ' filled bar (standard display)
         If pos <= mpeak Then set_led
      EndIf
      If pos = lastpeak Then
set_led:
        barbitsH.7 = 1 ' bit (led) is on
      EndIf
      Inc pos
   Loop While pos < WIDTH

Return ' end of Set_BarBits

'----------- end of program, 357 rom, 59 ram (optimiser = 2)
 
No sé si mi maestro entra en este foro. No creo, pero puedes esperar si lo ves conveniente.

Mientras esperamos a mi maestro te comento lo que he visto yo:
La bola de cristal es que la tengo rota ahora mismo y tengo muchas dudas de lo que no dices:
  1. ¿Como se conecta?
  2. ¿Que se conecta?
  3. ¿En que web pillaste ese código?
  4. ¿Por qué no preguntas allí?
  5. ¿Que microcontrolador?
  6. ¿Que leds?
  7. ¿Que lcd?
  8. ¿Que lenguaje de programación? **Parece basic
    1. ¿Que basic?
    2. ¿Con que compilador?
    3. ¿Es interpretado?
 
No sé si mi maestro entra en este foro. No creo, pero puedes esperar si lo ves conveniente.

Mientras esperamos a mi maestro te comento lo que he visto yo:
La bola de cristal es que la tengo rota ahora mismo y tengo muchas dudas de lo que no dices:
  1. ¿Como se conecta?
  2. ¿Que se conecta?
  3. ¿En que web pillaste ese código?
  4. ¿Por qué no preguntas allí?
  5. ¿Que microcontrolador?
  6. ¿Que leds?
  7. ¿Que lcd?
  8. ¿Que lenguaje de programación? **Parece basic
    1. ¿Que basic?
    2. ¿Con que compilador?
    3. ¿Es interpretado?
Scooter,
Sí, mira tus experiencias en programación, espero que seas nuestro principiante para enseñarnos cómo hacerlo, siempre aprendo, si intentas dar algún código de línea, entonces trato de entenderlo y podría ser que esto te ayude.

Muchas gracias.
Lahmun.
 
Arriba