/**
* @mainpage Large Display Clock
*
* @section overview_sec Overview
*
* Large display LED clock.
*
* @section history_sec Revision History
*
* @subsection v100 V1.00
* 5 Mar 2006, M.Gray, Initial release
*/
// Hardware specific configuration.
#include <18f252.h>
// External crystal oscillator.
#fuses HS
// Disable watch dog timer.
#fuses NOWDT
// Protect the code so it can't be read back.
#fuses NOPROTECT
// Disable the power-up enable timer.
#fuses NOPUT
// Disable the brown out detect.
#fuses NOBROWNOUT
// Disable the low voltage programming mode.
#fuses NOLVP
// We define types that are used for all variables. These are declared
// because each processor has a different sizes for int and long.
// The PIC compiler defines boolean, int8, int16, and int32.
/// Boolean value { false, true }
typedef boolean bool_t;
/// Signed 8-bit number in the range -128 through 127.
typedef signed int8 int8_t;
/// Unsigned 8-bit number in the range 0 through 255.
typedef unsigned int8 uint8_t;
/// Signed 16-bit number in the range -32768 through 32767.
typedef signed int16 int16_t;
/// Unsigned 16-bit number in the range 0 through 65535.
typedef unsigned int16 uint16_t;
/// Signed 32-bit number in the range -2147483648 through 2147483647.
typedef signed int32 int32_t;
/// Unsigned 32-bit number in the range 0 through 4294967296.
typedef unsigned int32 uint32_t;
/// IEEE 32-bit floating point number.
typedef struct
{
/// Array that holds 32-bit IEEE floating pointer number.
unsigned int8 value[4];
} float_t;
/// IEEE 64-bit floating point number.
typedef struct
{
/// Array that holds 64-bit IEEE floating point number.
unsigned int8 value[8];
} double_t;
// These compiler directives set the clock, SPI/I2C ports, and I/O configuration.
// Frequency of crystal
#use delay(clock=14318180)
#use rs232(baud=9600, xmit=PIN_B7, rcv=PIN_B6, STREAM=PC_HOST)
// We'll set the I/O direction so we can just read/write I/O pins.
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
/**
* @defgroup led LED Driver
*
* Drives the multiplex LED display.
*
* @{
*/
// Map I/O pin names to hardware pins.
/// LED Digit 1 - Port B3
#define IO_LED_DIGIT_1 PIN_B3
/// LED Digit 2 - Port C5
#define IO_LED_DIGIT_2 PIN_C5
#define IO_LED_SEGMENT_B PIN_C0
#define IO_LED_SEGMENT_F PIN_B4
#define IO_LED_SEGMENT_G PIN_B5
#define IO_CLK PIN_C3
#define IO_DATA PIN_C4
#define LED_COLON 0x01
#define LED_SEG_C 0x02
#define LED_SEG_D 0x04
#define LED_SEG_E 0x08
#define LED_SEG_B 0x10
#define LED_SEG_A 0x20
#define LED_SEG_F 0x40
#define LED_SEG_G 0x80
#define DIGIT_OFF 0x10
const uint8_t LED_SEG_ARRAY[] =
{
// Digit 0
LED_SEG_A | LED_SEG_B | LED_SEG_C | LED_SEG_D | LED_SEG_E | LED_SEG_F,
// Digit 1
LED_SEG_B | LED_SEG_C,
// Digit 2
LED_SEG_A | LED_SEG_B | LED_SEG_D | LED_SEG_E | LED_SEG_G,
// Digit 3
LED_SEG_A | LED_SEG_B | LED_SEG_C | LED_SEG_D | LED_SEG_G,
// Digit 4
LED_SEG_B | LED_SEG_C | LED_SEG_F | LED_SEG_G,
// Digit 5
LED_SEG_A | LED_SEG_C | LED_SEG_D | LED_SEG_F | LED_SEG_G,
// Digit 6
LED_SEG_A | LED_SEG_C | LED_SEG_D | LED_SEG_E | LED_SEG_F | LED_SEG_G,
// Digit 7
LED_SEG_A | LED_SEG_B | LED_SEG_C | LED_SEG_F,
// Digit 8
LED_SEG_A | LED_SEG_B | LED_SEG_C | LED_SEG_D | LED_SEG_E | LED_SEG_F | LED_SEG_G,
// Digit 9
LED_SEG_A | LED_SEG_B | LED_SEG_C | LED_SEG_D | LED_SEG_F | LED_SEG_G,
// Digit A
LED_SEG_A | LED_SEG_B | LED_SEG_C | LED_SEG_E | LED_SEG_F | LED_SEG_G,
// Digit B
LED_SEG_C | LED_SEG_D | LED_SEG_E | LED_SEG_F | LED_SEG_G,
// Digit C
LED_SEG_A | LED_SEG_D | LED_SEG_E | LED_SEG_F,
// Digit D
LED_SEG_B | LED_SEG_C | LED_SEG_D | LED_SEG_E | LED_SEG_G,
// Digit E
LED_SEG_A | LED_SEG_D | LED_SEG_E | LED_SEG_F | LED_SEG_G,
// Digit F
LED_SEG_A | LED_SEG_E | LED_SEG_F | LED_SEG_G,
// 0x10 - All segments off
0x00
};
uint8_t ledSegment1;
uint8_t ledSegment2;
/// 5mS clock rate
#define LED_PWM_RATE 576
uint16_t ledTimerCompare;
bool_t ledDigit1Flag;
/**
* Initialize the LED driver.
*/
void ledInit()
{
ledSegment1 = 0x00;
ledSegment2 = 0x00;
ledDigit1Flag = false;
ledTimerCompare = LED_PWM_RATE;
CCP_1 = LED_PWM_RATE;
set_timer1(ledTimerCompare);
setup_ccp1( CCP_COMPARE_INT );
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_8);
}
uint8_t ledGetSegments (uint8_t digit)
{
if (digit > sizeof(LED_SEG_ARRAY))
return 0x00;
return LED_SEG_ARRAY[digit];
}
void ledSetSegments (uint8_t segment1, uint8_t segment2)
{
ledSegment1 = segment1;
ledSegment2 = segment2;
}
void ledWriteSegments (uint8_t segments)
{
output_a (segments & 0x2f);
output_bit (IO_LED_SEGMENT_B, (segments & LED_SEG_B));
output_bit (IO_LED_SEGMENT_F, (segments & LED_SEG_F));
output_bit (IO_LED_SEGMENT_G, (segments & LED_SEG_G));
}
#INT_CCP1
void ledTimer()
{
// Setup the next interrupt for the operational mode.
ledTimerCompare += LED_PWM_RATE;
CCP_1 = ledTimerCompare;
if (ledDigit1Flag)
{
output_low (IO_LED_DIGIT_1);
ledDigit1Flag = false;
ledWriteSegments (ledSegment1);
output_high (IO_LED_DIGIT_2);
} else {
output_low (IO_LED_DIGIT_2);
ledDigit1Flag = true;
ledWriteSegments (ledSegment2);
output_high (IO_LED_DIGIT_1);
} // END if-else
}
/** @} */
/**
* @defgroup sys System Library Functions
*
* Generic system functions similiar to the C run-time library.
*
* @{
*/
/**
* Initialize the system library and global resources.
*/
void sysInit()
{
// Set all outputs low.
output_a (0x00);
output_b (0x00);
output_c (0x00);
// Configure the port direction (input/output).
set_tris_a (0x10);
set_tris_b (0x47);
set_tris_c (0x1c);
// Disable all ADC ports.
setup_adc_ports (NO_ANALOGS);
port_b_pullups (true);
}
/** @} */
/**
* @defgroup app Device application
*
* Provides the main functionality for the device.
*
* @{
*/
/**
* Initialize the application specific variables and required processor resources.
*/
void appInit()
{
}
uint8_t head;
uint8_t tail;
uint8_t buffer[256];
void writeSerial (uint8_t text)
{
buffer[head] = text;
++head;
}
void serialUpdate ()
{
if (head == tail)
return;
disable_interrupts (GLOBAL);
fputc (buffer[tail], PC_HOST);
enable_interrupts(GLOBAL);
++tail;
}
unsigned char read_i2c(void);
void i2c_interrupt_handler(void);
void i2c_initialize(void);
void i2c_error(void);
void write_i2c(unsigned char transmit_byte);
#define RX_BUF_LEN 4
unsigned char slave_buffer[RX_BUF_LEN];
int buffer_index;
#byte PIC_SSPBUF = 0xfc9
#byte PIC_SSPADD = 0xfc8
#byte PIC_SSPSTAT = 0xfc7
#byte PIC_SSPCON1 = 0xfc6
#byte PIC_PIE1 = 0xf9d
#byte PIC_TRISC = 0xf94
#byte PIC_SSPCON2 = 0xfc5
/* Bit defines */
#define PIC_SSPSTAT_BIT_SMP 0x80
#define PIC_SSPSTAT_BIT_CKE 0x40
#define PIC_SSPSTAT_BIT_DA 0x20
#define PIC_SSPSTAT_BIT_P 0x10
#define PIC_SSPSTAT_BIT_S 0x08
#define PIC_SSPSTAT_BIT_RW 0x04
#define PIC_SSPSTAT_BIT_UA 0x02
#define PIC_SSPSTAT_BIT_BF 0x01
#define PIC_SSPCON1_BIT_WCOL 0x80
#define PIC_SSPCON1_BIT_SSPOV 0x40
#define PIC_SSPCON1_BIT_SSPEN 0x20
#define PIC_SSPCON1_BIT_CKP 0x10
#define PIC_SSPCON1_BIT_SSPM3 0x08
#define PIC_SSPCON1_BIT_SSPM2 0x04
#define PIC_SSPCON1_BIT_SSPM1 0x02
#define PIC_SSPCON1_BIT_SSPM0 0x01
#define PIC_SSPCON2_BIT_GCEN 0x80
#define PIC_SSPCON2_BIT_ACKSTAT 0x40
#define PIC_SSPCON2_BIT_ACKDT 0x20
#define PIC_SSPCON2_BIT_ACKEN 0x10
#define PIC_SSPCON2_BIT_RCEN 0x08
#define PIC_SSPCON2_BIT_PEN 0x04
#define PIC_SSPCON2_BIT_RSEN 0x02
#define PIC_SSPCON2_BIT_SEN 0x01
bool_t readyFlag = false;
uint8_t data[2];
#INT_SSP
void ssp_interupt ()
{
unsigned char temp_sspstat;
unsigned char this_byte;
/* Mask out the unnecessary bits */
temp_sspstat = PIC_SSPSTAT & 0x2D;
switch (temp_sspstat)
{
// Write operation, last byte was an address, buffer is full
case 0x09:
// Reset the buffer pointer.
buffer_index = 0;
// Dummy ready of buffer.
this_byte = read_i2c();
break;
// Write operation, last byte was data, buffer is full
case 0x29:
// Read the byte.
this_byte = read_i2c();
slave_buffer[buffer_index] = this_byte;
if (buffer_index != RX_BUF_LEN)
++buffer_index;
if (buffer_index == 2)
{
data[0] = slave_buffer[0];
data[1] = slave_buffer[1];
readyFlag = true;
}
break;
default:
break;
}
}
/* This function returns the byte in SSPBUF */
unsigned char read_i2c(void)
{
return PIC_SSPBUF;
}
uint8_t appGetAddress()
{
if (input(PIN_B1) == 0)
return 0x40;
if (input(PIN_B2) == 0)
return 0x42;
}
void appRun(uint8_t address)
{
head = 0;
tail = 0;
ledSetSegments (ledGetSegments(0x0a), ledGetSegments(0x0c));
while (PIC_SSPCON2 & 0x1f);
// Clear the SSPSTAT register.
PIC_SSPSTAT = 0x00;
PIC_SSPCON1 = 0x36;
PIC_SSPADD = address;
enable_interrupts(INT_SSP);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
for (;;)
{
if (readyFlag)
{
readyFlag = false;
ledSetSegments (data[0], data[1]);
}
}
}
/** @} */
/// Function where everything gets started.
void main()
{
// Configure the basic system.
sysInit();
// Wait for the power converter chains to stabilize.
delay_ms (100);
// Setup the subsystems.
appInit();
ledInit();
// Run the end application.
appRun(appGetAddress());
}