Subversion Repositories group.electronics

Rev

Rev 126 | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * lmd.c
 *
 *  Created on: 30/11/2013
 *      Author: pfowler
 */

#include <avr/io.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <math.h>

#include "avrutil.h"
#include "lmd.h"

#define LMD_NOOP                0x00
#define LMD_DIGIT0              0x01
#define LMD_DIGIT1              0x02
#define LMD_DIGIT2              0x03
#define LMD_DIGIT3              0x04
#define LMD_DIGIT4              0x05
#define LMD_DIGIT5              0x06
#define LMD_DIGIT6              0x07
#define LMD_DIGIT7              0x08
#define LMD_DECODE_MODE 0x09
#define LMD_INTENSITY   0x0a
#define LMD_SCAN_LIMIT  0x0b
#define LMD_SHUTDOWN    0x0c
#define LMD_DISPLAY_TEST 0x0f


void lmd_intensity(uint8_t max, uint8_t i) {
        lmd_writeReg(max, LMD_INTENSITY, i);
}

void lmd_scanlimit(uint8_t max, uint8_t l) {
        lmd_writeReg(max, LMD_SCAN_LIMIT, l);
}

void lmd_shutdown(uint8_t max, uint8_t s) {
        lmd_writeReg(max, LMD_SHUTDOWN, s);
}

void lmd_decodemode(uint8_t max, uint8_t d) {
        lmd_writeReg(max, LMD_DECODE_MODE, d);
}



void lmd_init(uint8_t pinx_addr,
                uint8_t clk_pin, uint8_t load_pin, uint8_t data_pin,
                uint8_t numMax) {
        lmd.pin = pinx_addr;
        lmd.ddr = pinx_addr + 1;
        lmd.port = pinx_addr + 2;
        lmd.clk = clk_pin;
        lmd.load = load_pin;
        lmd.data = data_pin;
        lmd.numMax = numMax;

        lmd.dps = malloc(lmd.numMax * sizeof(uint8_t));


        sbi(lmd.ddr, lmd.clk);
        sbi(lmd.ddr, lmd.load);
        sbi(lmd.ddr, lmd.data);

        _delay_us(100);
                                                                                                // Defaults
        lmd_writeRegAll(LMD_INTENSITY, 0x01);                   // Lowest intensity
        lmd_writeRegAll(LMD_SCAN_LIMIT, 0x07);                  // Use all leds
        lmd_writeRegAll(LMD_SHUTDOWN, 0x01);                    // Shutdown
        lmd_writeRegAll(LMD_DECODE_MODE, 0x00);         // No decoding

        _delay_us(100);

        lmd_clearAll();
}

void lmd_clearAll(void) {
        uint8_t c;
        for (c=1; c<=8; c++) {
                lmd_writeRegAll(c, 0x00);
        }
}

void lmd_dp(uint8_t max, uint8_t digit) {
        lmd.dps[max] = digit;
}

void lmd_print_u32(uint8_t max, uint32_t value) {
        const uint8_t DIGIT_COUNT = 8;

        uint8_t i;
        for (i=1; i<=DIGIT_COUNT; i++) {
                uint32_t power = (uint32_t)pow(10, i);
                if (i != 1) power++;
                uint8_t val = ((value % power) / (power/10)) ;

                if (rbi(lmd.dps[max], i-1))
                        lmd_writeReg(max, i, val | 0xf0 );
                else
                        lmd_writeReg(max, i, val);
        }
}

void lmd_print_u16(uint8_t max, uint16_t value) {
        const uint8_t DIGIT_COUNT = 5;

        uint8_t i;
        for (i=1; i<=DIGIT_COUNT; i++) {
                uint32_t power = (uint32_t)pow(10, i);
                if (i != 1) power++;
                uint8_t val = ((value % power) / (power/10)) ;

                if (rbi(lmd.dps[max], i-1))
                        lmd_writeReg(max, i, val | 0xf0 );
                else
                        lmd_writeReg(max, i, val);
        }

}

void lmd_print_u8(uint8_t max, uint8_t value) {
        const uint8_t DIGIT_COUNT = 3
                        ;
        uint8_t i;
        for (i=1; i<=DIGIT_COUNT; i++) {
                uint32_t power = (uint32_t)pow(10, i);
                if (i != 1) power++;
                uint8_t val = ((value % power) / (power/10)) ;

                if (rbi(lmd.dps[max], i-1))
                        lmd_writeReg(max, i, val | 0xf0 );
                else
                        lmd_writeReg(max, i, val);
        }
}

void lmd_writeReg(uint8_t max, uint8_t reg, uint8_t val) {
        uint8_t c;
        cbi(_SFR_IO8(lmd.port), lmd.load);
        for (c=lmd.numMax; c< max; c--) {
                lmd_writeByte(0x00);
                lmd_writeByte(0x00);
        }

        lmd_writeByte(reg);
        lmd_writeByte(val);

        for (c=max-1; c<= 1; c--) {
                lmd_writeByte(0x00);
                lmd_writeByte(0x00);
        }
        sbi(_SFR_IO8(lmd.port), lmd.load);
}

void lmd_writeRegAll(uint8_t reg, uint8_t val) {
        uint8_t c;
        cbi(_SFR_IO8(lmd.port), lmd.load);
        for (c=1; c<=lmd.numMax; c++) {
                lmd_writeByte(reg);
                lmd_writeByte(val);
        }
        sbi(_SFR_IO8(lmd.port), lmd.load);
}

void lmd_writeByte(uint8_t dataout) {
        uint8_t mask;
        uint8_t i = 8;
        for (i=8; i>0; i--) {
                mask = 0x01 << (i - 1);
                cbi(_SFR_IO8(lmd.port), lmd.clk);
                if (dataout & mask)             // Send 1 bit at a time
                        sbi(_SFR_IO8(lmd.port), lmd.data);
                else
                        cbi(_SFR_IO8(lmd.port), lmd.data);
                sbi(_SFR_IO8(lmd.port), lmd.clk);
        }

}

void lmd_test(void) {
        lmd_writeRegAll(LMD_DECODE_MODE,0x00);
        lmd_writeRegAll(8,0b01001110);
        lmd_writeRegAll(7,0b01111110);
        lmd_writeRegAll(6,0b01111110);
        lmd_writeRegAll(5,0b00001110);
        lmd_writeRegAll(4,0b01110111);
        lmd_writeRegAll(3,0b01011011);
        lmd_writeRegAll(2,0b01011011);
        lmd_writeRegAll(1,0x80);
}