/*  Filename     PKIT6.C
    Description  PKIT-6 General VU Meter
    Hardware     PKIT-6
    Compiler     CCS PCW C Complier V3.28
    Engineer     Kriangsak B.
    Company      Sila Research Co.,Ltd. */

#include <12f675.h>
#fuses INTRC_IO,PUT,NOWDT,NOMCLR,NOBROWNOUT,NOCPD,PROTECT

#use delay (clock=4000000)

#define DATA PIN_A0
#define STR PIN_A1
#define CLK PIN_A2
#define VSEL PIN_A3
#define LSEL PIN_A5

/********** SUB FUNCTION **********/

void out595 (int16 x) {                     // out x to 74hc595=2
    char i;
    output_low (CLK);
    output_low (STR);
    for (i=0;i<=15;++i) {
        if (x & 0x8000) output_high (DATA); else output_low (DATA);
        x <<= 1;
        output_high (CLK);
        output_low (CLK);
    }
    output_high (STR);
    output_low (STR);
}

int16 setmax (int16 y) {                    // set led max
    char i;
    int16 m;
    m = 0x8000;
    for (i=0;i<=15;i++) {
        if ((y & m)==m) return (m);
        m = m >> 1;
    }
    return (0);
}

/********** MAIN **********/

void main (void) {
    char i,c;
    int16 x1,X2,X3,X4,X5,x,y,m;

    setup_adc_ports (AN3_ANALOG);
    setup_adc_ports (VSS_VDD);
    setup_adc (ADC_CLOCK_INTERNAL);
    set_adc_channel (3);
    output_high (VSEL);
    output_high (LSEL);

    c = 0;
    while (1) {
        x5 = x4;                            // average
        x4 = x3;
        x3 = x2;
        x2 = x1;
        x1 = read_adc ();                   // x = 0-1023 (10-bit adc) , 0-5 Volt
        x = (x1+x2+x3+x4+x5) / 5;

        if (input (VSEL)==1) {
            if (x>210) x = 210;             // 40+170 Aprox 0.2-1.0 Volt
            else if (x<40) x = 40;
            x = (x - 40) * 6;
        }

        y = 0;
        for (i=0;i<=15;i++) {               // change to 16 level led
            if (x>0) {
                y = (y << 1) | 1;
                if (x>64) x = x - 64;
                else x = 0;
            }
        }
        if (c==0 || y>m) {                  // check max & set
            c = 100;
            m = setmax (y);
        }
        out595 (y | m);                     // out to led (scan 20% for protect LED)
        delay_ms (2);
        out595 (0);
        delay_ms (8);
        if (input (LSEL)==0) c--;           // latch max or not-latch
    }
}

