| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- /*
- * Copyright (c) 2022-2024, Xiaohua Semiconductor Co., Ltd.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2024-12-30 CDT first version
- */
- /*
- * 程序清单:这是 Soft I2C 设备使用例程。
- * 例程导出了 sw_i2c_sample 到控制终端。
- * 命令调用格式:sw_i2c_sample cmd_id [options]
- * 命令解释:命令第二个参数是要使用的Soft I2C设备的命令,为空则打印命令使用说明
- * 程序功能:查找Soft I2C设备,读写I2C设备寄存器。
- * 注意:测试要用逻辑分析仪或示波器抓取信号
- */
- #include <rtthread.h>
- #include <rtdevice.h>
- #include <board.h>
- #include "rtconfig.h"
- #include "rtdef.h"
- #if defined(RT_USING_I2C)
- #if defined(BSP_USING_I2C1_SW)
- /* using i2c1 control oled12864 */
- #define SW_I2C_NAME "i2c1_sw"
- #define SSD1306_ADDR (0x78U >> 1)
- #define SSD1306_MD_CMD (0x00U)
- #define SSD1306_MD_DATA (0x40U)
- /* symbol parameters: width pixles, lenght pixels */
- #define SYM_W_PIX (8U)
- #define SYM_H_PIX (8U)
- /* ssd ohysical parameters */
- #define SSD_PAGE_SIZE (8U)
- #define SSD_COL_SIZE (128U)
- /* each page 8 pix */
- #define PAGE_PIX_SIZE (8U)
- /* each byte set horizontal 1 pix */
- #define SYM_W_BYTE (SYM_W_PIX / 1)
- /* each byte set vertical 8 pix */
- #define SYM_H_BYTE (SYM_H_PIX / 8)
- /* each character occupis */
- #define SYM_BYTE_SIZE (SYM_W_BYTE * SYM_H_BYTE)
- /* soft i2c command defines */
- enum SW_I2C_CMD
- {
- SW_I2C_INIT = 0x01,
- SSD1306_CMD_INIT,
- SSD1306_CMD_DISPLAY,
- SSD1306_CMD_DEINIT,
- };
- /* local variables */
- struct rt_i2c_msg msg;
- rt_uint8_t ssd_init_array[30];
- rt_uint8_t logo_array[5][SYM_BYTE_SIZE];
- /* local functions */
- static void ssd1306_init(struct rt_i2c_bus_device *i2c_dev);
- static void ssd1306_roll_display(struct rt_i2c_bus_device *i2c_dev);
- static void ssd1306_deinit(struct rt_i2c_bus_device *i2c_dev);
- /* write_reg ssd1306 basic opertion */
- static void ssd1306_write_single_reg(struct rt_i2c_bus_device *i2c_dev,
- rt_bool_t is_write_cmd, rt_uint8_t data)
- {
- rt_uint8_t buff[2];
- struct rt_i2c_msg msgs;
- msgs.addr = SSD1306_ADDR;
- msgs.flags = RT_I2C_WR;
- if (RT_TRUE == is_write_cmd)
- {
- buff[0] = SSD1306_MD_CMD;
- }
- else
- {
- buff[0] = SSD1306_MD_DATA;
- }
- buff[1] = data;
- msgs.buf = buff;
- msgs.len = 2;
- if (1 != rt_i2c_transfer(i2c_dev, &msgs, 1))
- {
- rt_kprintf("failed to send cmd\n");
- }
- }
- /* write_reg ssd1306 basic opertion */
- static void ssd1306_write_mult_reg(struct rt_i2c_bus_device *i2c_dev,
- rt_bool_t is_write_cmd, rt_uint8_t len, rt_uint8_t *data
- /*rt_uint8_t data*/)
- {
- rt_uint8_t *buff = NULL;
- struct rt_i2c_msg msgs;
- msgs.addr = SSD1306_ADDR;
- msgs.flags = RT_I2C_WR;
- buff = (rt_uint8_t *)rt_malloc((len + 1) * sizeof(rt_uint8_t));
- if (RT_TRUE == is_write_cmd)
- {
- buff[0] = SSD1306_MD_CMD;
- }
- else
- {
- buff[0] = SSD1306_MD_DATA;
- }
- rt_memcpy(buff + 1, data, len);
- msgs.buf = buff;
- msgs.len = len + 1;
- if (1 != rt_i2c_transfer(i2c_dev, &msgs, 1))
- {
- rt_kprintf("failed to send cmd\n");
- }
- rt_free(buff);
- buff = NULL;
- }
- static int sw_i2c_sample(int argc, char *argv[])
- {
- static struct rt_i2c_bus_device *rt_i2c_dev;
- /* print soft i2c usage */
- if (argc <= 1)
- {
- rt_kprintf("soft i2c usage as following:\n");
- rt_kprintf("sw_i2c_sample %d: soft i2c init\n", SW_I2C_INIT);
- rt_kprintf("sw_i2c_sample %d: oled ssd1306 init\n", SSD1306_CMD_INIT);
- rt_kprintf("sw_i2c_sample %d: write ssd1306 \n", SSD1306_CMD_DISPLAY);
- rt_kprintf("sw_i2c_sample %d: turn off ssd1306\n", SSD1306_CMD_DEINIT);
- return -RT_ERROR;
- }
- switch (*argv[1] - '0')
- {
- case SW_I2C_INIT:
- rt_i2c_dev = (struct rt_i2c_bus_device *)rt_device_find(SW_I2C_NAME);
- if (NULL == rt_i2c_dev)
- {
- rt_kprintf("failed to find i2c device %s\n", SW_I2C_NAME);
- return -RT_ERROR;
- }
- break;
- /* communicate with eeprom to soft i2c read function */
- case SSD1306_CMD_INIT:
- ssd1306_init(rt_i2c_dev);
- break;
- /* communicate with ssd1306 to soft i2c read function */
- case SSD1306_CMD_DISPLAY:
- ssd1306_roll_display(rt_i2c_dev);
- break;
- case SSD1306_CMD_DEINIT:
- ssd1306_deinit(rt_i2c_dev);
- break;
- default:
- rt_kprintf("unkwon command\n");
- break;
- }
- return RT_EOK;
- }
- /* ssd1306 de-init and turn off */
- static void ssd1306_deinit(struct rt_i2c_bus_device *i2c_dev)
- {
- rt_uint8_t ssd_deinit_array[] =
- {
- 0X8D, /* set charge pump */
- 0X10, /* turn off charge pump */
- 0XAE, /* OLED sleep */
- };
- ssd1306_write_mult_reg(i2c_dev, RT_TRUE,
- sizeof(ssd_deinit_array) / sizeof(ssd_deinit_array[0]),
- ssd_deinit_array);
- }
- /* ssd oled initialize */
- static void ssd1306_init(struct rt_i2c_bus_device *i2c_dev)
- {
- ssd1306_write_mult_reg(i2c_dev, RT_TRUE,
- sizeof(ssd_init_array) / sizeof(ssd_init_array[0]),
- ssd_init_array);
- }
- /*
- Function: write a heigh * width = 16 *16 --->pixel: 16 * 8character
- Input: void
- Output: void
- Data: 20210828
- */
- void mOledWriteCharHnWm(struct rt_i2c_bus_device *i2c_dev,
- uint8_t page, uint8_t col, uint8_t *ArrChar)
- {
- if (ArrChar == NULL)
- return;
- rt_kprintf("x=%3d, y=%d\n", col, page);
- for (uint8_t page_idx = 0; page_idx < SYM_H_BYTE; page_idx++)
- {
- /* set start page: page0-page1 */
- ssd1306_write_single_reg(i2c_dev, RT_TRUE, 0xb0 + page + page_idx);
- /* lower 4-bit address of column start */
- ssd1306_write_single_reg(i2c_dev, RT_TRUE, 0x00 + ((col & 0x0F) >> 0));
- /* higher 4-bit address of column start */
- ssd1306_write_single_reg(i2c_dev, RT_TRUE, 0x10 + ((col & 0xF0) >> 4));
- /* send a character(total BYTE_CHAR byte) from array */
- ssd1306_write_mult_reg(i2c_dev, RT_FALSE, SYM_W_BYTE,
- ArrChar + SYM_W_BYTE * page_idx);
- }
- }
- /* fill oled with character "XHSC" */
- static void ssd1306_roll_display(struct rt_i2c_bus_device *i2c_dev)
- {
- rt_uint8_t base_col, base_page;
- rt_uint8_t offset_page, offset_col;
- rt_uint16_t idx;
- /* using a write times related variable control position */
- static rt_uint16_t u16WriteTimes = 0;
- if (u16WriteTimes >= (SSD_COL_SIZE / SYM_W_PIX) * (SSD_PAGE_SIZE / (SYM_H_PIX / PAGE_PIX_SIZE)))
- {
- u16WriteTimes = 0;
- }
- /* each page write, eg. base_page = 7 / (128 / 8) = 0 */
- base_page = u16WriteTimes / (SSD_COL_SIZE / SYM_W_PIX);
- /* eg. base_col = (7 % (128 / 8)) * 8 = 56 */
- base_col = (u16WriteTimes % (SSD_COL_SIZE / SYM_W_PIX)) * SYM_W_PIX;
- offset_page = 0;
- offset_col = 0;
- /* each write cycle finish the data writing in array */
- for (idx = 0; idx < sizeof(logo_array) / sizeof(logo_array[0]); idx++)
- {
- offset_col = idx * SYM_W_PIX;
- if (base_col + offset_col >= SSD_COL_SIZE)
- {
- /*
- base_col + offset_col = [128, 256), page_offset = 1,
- base_col + offset_col = [256, 384), page_offset = 2,
- ...
- */
- offset_page = (base_col + offset_col) / SSD_COL_SIZE;
- }
- mOledWriteCharHnWm(i2c_dev, ((base_page + offset_page) * SYM_H_BYTE) % SSD_PAGE_SIZE, (base_col + offset_col) % SSD_COL_SIZE, *(logo_array + idx));
- }
- u16WriteTimes++;
- }
- rt_uint8_t ssd_init_array[] =
- {
- 0xAE, /* display off */
- 0x20, /* Set Memory Addressing Mode */
- 0x10, /* Set addressing orient */
- 0xB0, /* Set Page Start Address for Page Addressing Mode,0-7 */
- 0xC8, /* Set COM Output Scan Direction */
- 0x00, /* set low column address */
- 0x10, /* set high column address */
- 0x40, /* set start line address */
- 0x81, /* set contrast control register */
- 0xFF, /* breightness 0x00~0xff */
- 0xA1, /* set segment re-map 0 to 127 */
- 0xA6, /* set normal display */
- 0xA8, /* set multiplex ratio(1 to 64) */
- 0x3F, /* */
- 0xC8, /* */
- 0xA4, /* 0xa4,Output follows RAM content;0xa5,Output ignores RAM content */
- 0xD3, /* set display offset */
- 0x00, /* not offset */
- 0xD5, /* set display clock divide ratio/oscillator frequency */
- 0xF0, /* set divide ratio */
- 0xD9, /* set pre-charge period */
- 0x22, /* */
- 0xDA, /* set com pins hardware configuration */
- 0x12, /* */
- 0xDB, /* set vcomh */
- 0x20, /* 0x20,0.77xVcc */
- 0x8D, /* set DC-DC enable */
- 0x14, /* */
- 0xAF, /* --turn on oled panel */
- };
- rt_uint8_t logo_array[][SYM_BYTE_SIZE] =
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x44, 0x44, 0x6C, 0x74, 0x54, 0x6C, 0x44, 0x44, /*"X"*/
- 0x44, 0x7C, 0x54, 0x10, 0x10, 0x54, 0x7C, 0x44, /*"H"*/
- 0x00, 0x68, 0x54, 0x54, 0x54, 0x54, 0x24, 0x00, /*"S"*/
- 0x38, 0x6C, 0x44, 0x44, 0x44, 0x44, 0x24, 0x00, /*"C"*/
- };
- MSH_CMD_EXPORT(sw_i2c_sample, soft i2c sample);
- #endif /* BSP_USING_I2C1_SW */
- #endif/* RT_USING_I2C */
- /*
- EOF
- */
|