/** * @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()); }