/*******************************************************************************/ /* Project : AVR-Lab I2C for KMM */ /* File : I2C_skal.c */ /* Author : Olov Andersson */ /* Date : 2022-09-27 */ /* Version : 4.1 */ /* Platform : ATmega16 Mounted on the DALIA Board */ /* RTCchip : PCF8563 */ /*******************************************************************************/ /* Pin List: */ /* PA0-PA7 : Out : Data to Clock 7-seg module */ /* PB0-PB7 : Out : Data to Digital Discovery */ /* PC0 (SCL) : : I2C Clock */ /* PC1 (SDA) : : I2C Data */ /* PC2-PC7 : : Not Used (Not available on the DALIA Board) */ /* PD0-PD1 : Out : Address to 7-seg module */ /* PD2 : Out : Data to Digital Discovery */ /* PD3 (INT1): In : Keyboard Strobe */ /* PD4-PD7 : In : Keyboard Data */ /*******************************************************************************/ /* Thread List: */ /* */ /* (1) : Timer 0 -Interrupt : Update the display value in approx 250 Hz */ /* */ /* (2) : Timer 1 -Interrupt : Fetch the Time from the RTC ones a sec */ /* */ /* (3) : INT1 -Interrupt : Input data from Keyboard and update Display */ /* */ /* (4) : Main : An infinite loop to do some work */ /* */ /*******************************************************************************/ #include #include #include // #define I2C_DEBUG // Global declarations #define I2C_BUFF_SIZE 32 #define DISP_BUFF_SIZE 4 #define RTC_SLA 0xa2 // Including R/W bit volatile uint8_t I2C_write_buffer[I2C_BUFF_SIZE]; volatile uint8_t I2C_read_buffer[I2C_BUFF_SIZE]; volatile uint8_t RTC_clock_on; volatile uint8_t DISP_value[DISP_BUFF_SIZE]; volatile uint8_t DISP_mark; volatile uint8_t DISP_mux; /*******************************************************************************/ /* I2C code part */ /* Read/write data on registers in the I2C connected RTC. */ /*******************************************************************************/ #define TW_START 0x08 #define TW_REPEATED_START 0x10 #define TW_MT_SLA_ACK 0x18 #define TW_MT_DATA_ACK 0x28 #define TW_MR_SLA_ACK 0x40 #define TW_MR_DATA_ACK 0x50 #define TW_MR_DATA_NOT_ACK 0x58 uint8_t I2C_RTC_Write(uint8_t rAddr, uint8_t N) { uint8_t i; TWCR = (1<>4) & 0x07; DISP_value[2] = I2C_read_buffer[1] & 0x0f; DISP_value[3] = (I2C_read_buffer[1]>>4) & 0x07; } } /*******************************************************************************/ /* Display code part */ /* Show DISP_value on a physical multiplexed 7-segment display module */ /* Show DISP_alarm_value on a physical multiplexed 7-segment display module */ /* The interrupt is trigged in 1 kHz, updating the "next" 7-seg. */ /* The four 7-seg is updated in total of (1 kHz) / 4 = 250 Hz */ /*******************************************************************************/ void DISP_init() { DISP_value[0] = 0; DISP_value[1] = 0; DISP_value[2] = 0; DISP_value[3] = 0; DISP_mux = 0; DDRA = 0xff; // All bits in port A are output DDRB = 0xff; // All bits in port B are output DDRD |= 0x03; // make PortD0 and D1 outputs. Do not engage the others. TCCR0 = 0x0a; // CTC Mode , 1/8 Prescaler OCR0 = 124; // approx. 1 kHz TIMSK |= (1<= (DISP_BUFF_SIZE-1)) { DISP_mux = 0; } else { DISP_mux++; }; clock_pattern = DISP_Segment[DISP_value[DISP_mux]]; if (DISP_mux == DISP_mark) { clock_pattern |= 0x80; // Add a decimal dot to the output }; #ifdef I2C_DEBUG // Code for Part B PORTA = 0; PORTD = DISP_mux; PORTA = clock_pattern; #else // Code for Part A PORTA = 0; PORTB = 0; PORTD = DISP_mux; PORTA = clock_pattern; PORTB = clock_pattern; #endif PORTD &= 0xfb; } /*******************************************************************************/ /* Keyboard code part */ /* The Keyboard strobe signal is triggering the INT1 */ /* Keyboard data are transferred to KB_handle through a cyclic FIFO Buffer */ /*******************************************************************************/ void KB_init() { // DDRD = 0; // All bits in port D are input MCUCR |= 0x0c; // Interrupt on rising edge. GIFR |= (1<> 4) & 0x0f; switch (key) { case 0x0a: // A: Save and Activate Alarm break; case 0x0b: // B: Inactivate Alarm break; case 0x0d: // D: Save New Time and continue to Set Clock Mode if (RTC_clock_on) { break; // Unable to save new time in Clock Mode }; RTC_set_time(); case 0x0c: // C: Set Clock Mode RTC_clock_on = 1; DISP_mark = 2; break; case 0x0e: // E: Set Edit Mode RTC_clock_on = 0; DISP_mark = DISP_BUFF_SIZE-1; break; default: // 0-9: Set value and continue to Move cursor if (RTC_clock_on) { break; // Unable to input digits in Clock Mode }; // ----------------------------------- ToDo ----------------------------------- // Write code here. case 0x0f: // F: Move Cursor if (RTC_clock_on) { break; // Unable to move cursor in Clock Mode }; if (DISP_mark == 0) { DISP_mark = DISP_BUFF_SIZE-1; } else { DISP_mark--; }; break; } } /*******************************************************************************/ /* Main */ /*******************************************************************************/ int main(void){ RTC_clock_on = 0; DISP_init(); RTC_init(); KB_init(); sei(); // Uncomment the following two lines when you are finished with the RTC_write_mode // function and if you want a reset of the RTC. RTC_Reset(); RTC_clock_on = 1; DISP_mark = 2; while (1) { } }