Go to most recent revision | 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);
}