Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Project:
- * Description:
- *
- *
- * Date:
- */
- #include "inc/stm8s.h"
- #include "inc/stm8s_gpio.h"
- #include <stdlib.h>
- #include "inc/uCLI.h"
- #define DS1307_ADDR 0xD0
- #define DS1307_CH_MASK 0x80
- #define DS1307_MODE_MASK 0x40
- #define DS1307_AMPM_MASK 0x20
- #define DS1307_BUF_SIZE 64
- // #define UART_BUF_LENGTH 0x10
- typedef enum DS1307_REGS
- {
- DS1307_REG_SEC = 0x00,
- DS1307_REG_MIN = 0x01,
- DS1307_REG_HOUR = 0x02,
- DS1307_REG_DAY = 0x03,
- DS1307_REG_DATE = 0x04,
- DS1307_REG_MONTH = 0x05,
- DS1307_REG_YEAR = 0x06,
- DS1307_REG_CONTROL = 0x07,
- DS1307_REG_RAM_START = 0x08,
- DS1307_REG_RAM_END = 0x3F
- }DS1307_REGS_t;
- typedef enum UART_STATUS
- {
- UART_BUF_EMPTY = 0x00,
- UART_BUF_UPDATED,
- UART_BUF_FULL,
- UART_BUF_READ, // If buffer contain valid but old data
- UART_BUF_OVERRUN, // Buffer hasn't been properly proceed and new data available
- UART_BUF_RESET_INDEX
- } UART_STATUS_t;
- CMD_BUF_t cmd_buf; // ring buffer to store commands from uart
- uint8_t ds1307_buf[DS1307_BUF_SIZE];
- const char* weekday[] = {"mon", "tue", "wed", "thu", "fri", "sat", "sun"};
- unsigned char time_str[30];// 2016/07/02 sat AM 12:04:36
- void uart_tx_string(unsigned char *str);
- //========================= Commands declarations ============================//
- enum CMD
- {
- CMD_NONE = 0x00,
- CMD_STOP_CLOCK,
- CMD_START_CLOCK,
- CMD_READ_DS1307,
- CMD_WRITE_DS1307,
- CMD_GET_TIME,
- CMD_SET_TIME
- };
- void cmd_none(void*);
- void cmd_start_clock(void*);
- void cmd_stop_clock(void*);
- // void cmd_get_time(void*);
- // void cmd_set_time(void*);
- void cmd_read_from_ds1307(void*);
- // void cmd_write_to_ds1307(void*);
- // this is may seems unclear, but just look at CMD_HASHED_t typedef
- const CMD_HASHED_t cmd_list[] =
- {
- [CMD_NONE].action = cmd_none,
- [CMD_STOP_CLOCK].action = cmd_stop_clock,
- [CMD_START_CLOCK].action = cmd_start_clock,
- [CMD_READ_DS1307].action = cmd_read_from_ds1307
- // {[CMD_WRITE_DS1307] = cmd_write_to_ds1307},
- // {[CMD_GET_TIME] = cmd_get_time},
- // {[CMD_SET_TIME] = cmd_set_time}
- };
- //====================== Commands declarations END ===========================//
- //================================= I2C ======================================//
- void I2C_init() // TODO: rewrite this function to more versatile
- {
- I2C->FREQR = (HSI_VALUE/(1e6));
- // For standard mode:
- // I2C_period = 2*CCR/F_master => CCR = F_master/(2*I2C_frequency)
- // Let choose I2C_frequency = 50 kHz
- I2C->CCRH = (uint8_t) (((HSI_VALUE)/(2*50000)) >> 8);
- I2C->CCRL = (uint8_t) (((HSI_VALUE)/(2*50000)) & 0xFF);
- I2C->TRISER = 16+1; // For standard mode
- I2C->CR1 = I2C_CR1_PE;
- I2C->CR2 = I2C_CR2_ACK;
- }
- inline void I2C_set_START_bit()
- {
- I2C->CR2 |= I2C_CR2_START;
- }
- inline void I2C_set_STOP_bit()
- {
- I2C->CR2 |= I2C_CR2_STOP;
- }
- inline void I2C_set_ACK_bit()
- {
- I2C->CR2 |= I2C_CR2_ACK;
- }
- inline void I2C_reset_ACK_bit()
- {
- I2C->CR2 &= ~I2C_CR2_ACK;
- }
- inline uint8_t I2C_is_busy()
- {
- return I2C->SR3 & I2C_SR3_BUSY;
- }
- inline void I2C_gen_START_event()
- {
- I2C_set_START_bit();
- while (!(I2C->SR1 & I2C_SR1_SB));
- }
- inline void I2C_gen_ADDRESS_event(uint8_t slave_addr)
- {
- I2C->DR = slave_addr;
- //uart_tx_string("F I2C_gen_ADDRESS_event. Slave addr set in DR.\n");
- while (!(I2C->SR1 & I2C_SR1_ADDR));
- //uart_tx_string("F I2C_gen_ADDRESS_event. Waiting ADDR flag.\n");
- I2C->SR3; // Dummy read to clear ADDR in SR1
- //uart_tx_string("F I2C_gen_ADDRESS_event. Dummy read of SR3 done.\n");
- }
- inline void I2C_wait_end_of_transmission()
- {
- uint8_t tmp_SR1;
- while (1)
- {
- tmp_SR1 = I2C->SR1;
- if ((tmp_SR1 & I2C_SR1_BTF) && (tmp_SR1 & I2C_SR1_TXE)) {break;}
- }
- }
- void I2C_master_tx (uint8_t *data_ptr, uint8_t length)
- {
- while (length--)
- {
- while(!(I2C->SR1 & I2C_SR1_TXE));
- I2C->DR = *data_ptr++;
- }
- }
- // TODO: add error check and rewrite possible infinite loops
- void I2C_master_send (uint8_t slave_addr, uint8_t *data_ptr, uint8_t length)
- {
- I2C_gen_START_event();
- I2C_gen_ADDRESS_event(slave_addr);
- I2C_master_tx(data_ptr, length);
- I2C_wait_end_of_transmission();
- I2C_set_STOP_bit();
- }
- // Method 2 from Ref Manual
- void I2C_master_receive (uint8_t slave_addr, uint8_t *data_buf, uint8_t length)
- {
- I2C_set_ACK_bit();
- I2C_gen_START_event();
- I2C->DR = slave_addr | 0x01;
- if (length == 1)
- {
- I2C_reset_ACK_bit();
- while (!(I2C->SR1 & I2C_SR1_ADDR));
- __critical // Workaround from errata. EV6_3
- {
- I2C->SR3; // Dummy read to clear ADDR in SR1
- I2C_set_STOP_bit();
- }
- while (!(I2C->SR1 & I2C_SR1_RXNE));
- *data_buf = I2C->DR;
- }
- else if (length == 2)
- {
- I2C->CR2 |= I2C_CR2_POS | I2C_CR2_ACK;
- while (!(I2C->SR1 & I2C_SR1_ADDR));
- __critical // Workaround from errata. EV6_1
- {
- I2C->SR3; // Dummy read to clear ADDR in SR1
- I2C_reset_ACK_bit();
- }
- while (!(I2C->SR1 & I2C_SR1_BTF));
- __critical // Workaround from errata. EV7_3
- {
- I2C_set_STOP_bit();
- *data_buf = I2C->DR;
- data_buf++;
- *data_buf = I2C->DR;
- }
- I2C->CR2 &= ~I2C_CR2_POS;
- }
- else // Number of bytes to transfer > 2
- {
- while (!(I2C->SR1 & I2C_SR1_ADDR)); // wait for EV6
- I2C->SR3; // Dummy read to clear ADDR in SR1
- while (length-- > 3)
- {
- while (!(I2C->SR1 & I2C_SR1_RXNE));
- *data_buf++ = I2C->DR;
- }
- while (!(I2C->SR1 & I2C_SR1_BTF)); // wait for EV7_2
- // EV7_2. Now DataN-2 is in DR, DataN-1 is in hw buffer. Set ACK=0,
- // read DataN-2 from DR, Program STOP=1, read DataN-1.
- I2C_reset_ACK_bit();
- __critical // Workaround from errata
- {
- *data_buf++ = I2C->DR;
- I2C_set_STOP_bit();
- *data_buf++ = I2C->DR;
- }
- while (!(I2C->SR1 & I2C_SR1_RXNE)); // wait for EV7
- *data_buf++ = I2C->DR;
- }
- }
- //============================== I2C END =====================================//
- //=============================== DS1307 =====================================//
- void ds1307_write (uint8_t reg_addr, uint8_t *data_ptr, uint8_t length)
- {
- I2C_gen_START_event();
- I2C_gen_ADDRESS_event(DS1307_ADDR);
- // Set DS1307 address pointer
- I2C_master_tx(®_addr, sizeof(reg_addr));
- I2C_wait_end_of_transmission();
- // Send data
- I2C_master_tx(data_ptr, length);
- // Close transmission
- I2C_wait_end_of_transmission();
- I2C_set_STOP_bit();
- }
- void ds1307_read(uint8_t reg_addr, uint8_t *data_buf_ptr, uint8_t length)
- {
- //uart_tx_string("FUNCT ds1307_read.\n");
- I2C_gen_START_event();
- //uart_tx_string("Start event generated.\n");
- I2C_gen_ADDRESS_event(DS1307_ADDR);
- //uart_tx_string("Address event generated.\n");
- I2C_master_tx(®_addr, sizeof(reg_addr));
- // uart_tx_string("Register address transmission in progress.\n");
- I2C_wait_end_of_transmission();
- //uart_tx_string("Register address transmitted.\n");
- I2C_master_receive(DS1307_ADDR, data_buf_ptr, length);
- }
- //============================= DS1307 END ===================================//
- //================================ UART ======================================//
- void UART1_init(void)
- {
- // Baudrate 9600 for F_CPU = 16 MHz
- UART1->BRR2 = 0x03;
- UART1->BRR1 = 0x68;
- UART1->CR1 = 0x00;
- UART1->CR2 = UART1_CR2_REN | UART1_CR2_RIEN | UART1_CR2_TEN;
- }
- // Отправка байта
- inline void uart_tx_byte(uint8_t data)
- {
- while(!(UART1->SR & UART1_SR_TXE));
- UART1->DR = data;
- }
- // For debugging feature
- void uart_tx_string(unsigned char *str)
- {
- while(*str != 0) {uart_tx_byte(*str++);};
- }
- //============================ UART END ======================================//
- //================== Commands, settings and control ==========================//
- // data should be in ds1307 format
- void time_to_str(uint8_t *data, uint8_t *str)
- {
- // Year
- *str++ = '2';
- *str++ = '0';
- *str++ = (data[6] >> 4) + '0';
- *str++ = (data[6] & 0x0F) + '0';
- *str++ = '/';
- // Month
- *str++ = (data[5] >> 4) + '0';
- *str++ = (data[5] & 0x0F) + '0';
- *str++ = '/';
- // Day
- *str++ = (data[4] >> 4) + '0';
- *str++ = (data[4] & 0x0F) + '0';
- *str++ = ' ';
- { // Day of week
- const uint8_t *day = weekday[data[3] - 1];
- uint8_t i;
- for (i = 0; i < 3; i++)
- {
- *str++ = day[i];
- }
- *str++ = ' ';
- }
- // Hours
- if (data[2] & DS1307_MODE_MASK) // 12h mode
- {
- if (data[2] & DS1307_AMPM_MASK) {*str++ = 'P';}
- else {*str++ = 'A';}
- *str++ = 'M';
- *str++ = ' ';
- *str++ = (data[2] >> 4) + '0';
- *str++ = (data[2] & 0x0F) + '0';
- }
- else // 24h mode
- {
- *str++ = (data[2] >> 4) + '0';
- *str++ = (data[2] & 0x0F) + '0';
- }
- *str++ = ':';
- // Minutes
- *str++ = (data[1] >> 4) + '0';
- *str++ = (data[1] & 0x0F) + '0';
- *str++ = ':';
- // Seconds
- *str++ = ((data[0] >> 4) & 0x07) + '0'; // &0x07 to exclude CH bit
- *str++ = (data[0] & 0x0F) + '0';
- *str++ = '\n';
- *str = '\0';
- }
- void stop_clock()
- {
- ds1307_read(DS1307_REG_SEC, ds1307_buf, 1);
- ds1307_buf[0] |= DS1307_CH_MASK;
- ds1307_write(DS1307_REG_SEC, ds1307_buf, 1);
- }
- void start_clock()
- {
- ds1307_read(DS1307_REG_SEC, ds1307_buf, 1);
- ds1307_buf[0] &= ~DS1307_CH_MASK;
- ds1307_write(DS1307_REG_SEC, ds1307_buf, 1);
- }
- void get_time()
- {
- // Excluding control register
- ds1307_read(DS1307_REG_SEC, ds1307_buf, sizeof(ds1307_buf) - 1);
- time_to_str(ds1307_buf, time_str);
- uart_tx_string(time_str);
- }
- void set_time(uint8_t *data_buf_ptr, uint8_t length)
- {
- // Excluding control register
- ds1307_write(DS1307_REG_SEC, data_buf_ptr, \
- (length < sizeof(ds1307_buf) - 1) ? \
- (length) : (sizeof(ds1307_buf) - 2));
- }
- // ------------------- Command actions --------------------------//
- void cmd_none(void *ptr)
- {
- uart_tx_string("This is dummy command. No action has been taken.\n");
- }
- void cmd_start_clock(void *ptr)
- {
- start_clock();
- uart_tx_string("Clock is started.\n");
- }
- void cmd_stop_clock(void *ptr)
- {
- stop_clock();
- uart_tx_string("Clock is stopped.\n");
- }
- void cmd_read_from_ds1307(void *ptr)
- {
- uint8_t *data = ptr;
- /* data[0] -- register address
- * data[1] -- number of bytes to read
- */
- ds1307_read(data[0], ds1307_buf, data[1]);
- uart_tx_string("Read ");
- uart_tx_byte(data[1]);
- uart_tx_string(" bytes. Star addr = ");
- uart_tx_byte(data[0] + '0');
- uart_tx_byte('\n');
- {
- uint8_t i;
- uint8_t str[6];
- for (i = 0; i < data[1] - 1; i++)
- {
- _uitoa((unsigned int)ds1307_buf[i], str, 10);
- uart_tx_string(str);
- uart_tx_byte('\n');
- }
- }
- }
- //------------------------- Work with command buffer -------------------------//
- void check_cmd_buf(CMD_BUF_t *buf)
- {
- // This logic FIXED
- if (buf->status != CMD_BUF_RECEIVED) return;
- if (buf->data[2] < (sizeof(cmd_list)/sizeof(CMD_HASHED_t)))
- {
- uart_tx_string("Processing command\n");
- cmd_list[buf->data[2]].action( & buf->data[3]);
- }
- else
- {
- uart_tx_string("Unknown command ");
- uart_tx_byte(buf->data[2]);
- uart_tx_byte('\n');
- }
- uart_tx_string("Reset idx\n");
- buf->idx = 0;
- uart_tx_string("reset cmd_buf\n");
- {
- uint8_t i;
- for (i = 0; i < buf->size; i++) {buf->data[i] = 0;}
- }
- buf->status = CMD_BUF_EMPTY;
- uart_tx_string("Leaving check_cmd_buf\n");
- }
- //================ Commands, settings and control END ========================//
- void main(void)
- {
- // Disable clock prescaler. F_CPU = 16 MHz
- CLK->CKDIVR = 0x00;
- UART1_init();
- I2C_init();
- cmd_buf_init(&cmd_buf);
- uart_tx_string("Initialization complete.\n");
- __asm__("rim");
- while(1)
- {
- check_cmd_buf(&cmd_buf);
- }
- }
- void UART_RX_vector() __interrupt(18)
- {
- uart_tx_string("Entering RX ISR\n");
- // uart_tx_string("cmd_buf.idx = ");
- // uart_tx_byte(cmd_buf.idx + '0');
- // uart_tx_byte('\n');
- // Get data
- {
- uint8_t tmp;
- tmp = UART1->DR;
- switch (cmd_buf.status)
- {
- case CMD_BUF_EMPTY:
- {
- if (tmp == '#')
- {
- cmd_buf.data[cmd_buf.idx] = '#';
- cmd_buf.idx++;
- cmd_buf.status = CMD_BUF_RECEIVING;
- }
- break;
- }
- case CMD_BUF_RECEIVING:
- {
- if(cmd_buf.idx == 1)
- {
- cmd_buf.data[1] = tmp;
- }
- else
- {
- cmd_buf.data[cmd_buf.idx] = tmp;
- if ((cmd_buf.idx - 1) == cmd_buf.data[1])
- {
- // cmd_buf.idx++;
- // cmd_buf.data[cmd_buf.idx] = '\r';
- cmd_buf.status = CMD_BUF_RECEIVED;
- }
- }
- cmd_buf.idx++;
- break;
- }
- case CMD_BUF_RECEIVED:
- {
- uart_tx_string("Buffer is full. Command not processed yet.\n");
- break;
- }
- default: break;
- }
- }
- uart_tx_string("Leaving RX ISR\n");
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement