1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/pkg/landfall-examples/letux400_i2c/letux400_i2c.cc Sun Jan 03 17:28:05 2021 +0100
1.3 @@ -0,0 +1,157 @@
1.4 +/*
1.5 + * Access peripherals on the I2C bus.
1.6 + *
1.7 + * Copyright (C) 2018, 2020 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include <l4/devices/cpm-jz4730.h>
1.26 +#include <l4/devices/i2c-jz4730.h>
1.27 +#include <l4/devices/memory.h>
1.28 +
1.29 +#include <stdio.h>
1.30 +
1.31 +
1.32 +
1.33 +/* Scan the I2C bus by performing speculative reads from each device address. */
1.34 +
1.35 +static void i2c_scan(void *i2c_channel)
1.36 +{
1.37 + uint8_t buf[1];
1.38 + unsigned int address;
1.39 +
1.40 + for (address = 0; address < 0x20; address++)
1.41 + printf("%02x ", address);
1.42 + printf("\n");
1.43 +
1.44 + for (address = 0; address < 0x20; address++)
1.45 + printf("-- ");
1.46 +
1.47 + for (address = 0; address < 0x80; address++)
1.48 + {
1.49 + if ((address % 32) == 0)
1.50 + printf("\n");
1.51 +
1.52 + if (jz4730_i2c_read(i2c_channel, address, buf, 1))
1.53 + printf("%02x ", address);
1.54 + else
1.55 + printf("?? ");
1.56 + }
1.57 +
1.58 + printf("\n");
1.59 + for (address = 0; address < 0x20; address++)
1.60 + printf("-- ");
1.61 + printf("\n\n");
1.62 +}
1.63 +
1.64 +/* Interpret RTC registers. */
1.65 +
1.66 +static void rtc_datetime(uint8_t *rtcregs)
1.67 +{
1.68 + const char *weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
1.69 +
1.70 + printf("%s %d%d-%d%d-%d%d %d%d:%d%d:%d%d\n",
1.71 + weekdays[rtcregs[0x06] & 0x07],
1.72 + (rtcregs[0x08] & 0xf0) >> 4,
1.73 + rtcregs[0x08] & 0x0f,
1.74 + (rtcregs[0x07] & 0x10) >> 4,
1.75 + rtcregs[0x07] & 0x0f,
1.76 + (rtcregs[0x05] & 0x30) >> 4,
1.77 + rtcregs[0x05] & 0x0f,
1.78 + (rtcregs[0x04] & 0x30) >> 4,
1.79 + rtcregs[0x04] & 0x0f,
1.80 + (rtcregs[0x03] & 0x70) >> 4,
1.81 + rtcregs[0x03] & 0x0f,
1.82 + (rtcregs[0x02] & 0x70) >> 4,
1.83 + rtcregs[0x02] & 0x0f);
1.84 +}
1.85 +
1.86 +
1.87 +
1.88 +int main(void)
1.89 +{
1.90 + void *cpm;
1.91 + void *i2c, *i2c0;
1.92 +
1.93 + /* Peripheral memory. */
1.94 +
1.95 + l4_addr_t cpm_base = 0, cpm_base_end = 0;
1.96 + l4_addr_t i2c_base = 0, i2c_base_end = 0;
1.97 +
1.98 + /* Obtain resource details describing I/O memory. */
1.99 +
1.100 + printf("Access CPM...\n");
1.101 +
1.102 + if (get_memory("jz4730-cpm", &cpm_base, &cpm_base_end) < 0)
1.103 + return 1;
1.104 +
1.105 + printf("CPM at 0x%lx...0x%lx.\n", cpm_base, cpm_base_end);
1.106 +
1.107 + printf("Access I2C...\n");
1.108 +
1.109 + if (get_memory("jz4730-i2c", &i2c_base, &i2c_base_end) < 0)
1.110 + return 1;
1.111 +
1.112 + printf("I2C at 0x%lx...0x%lx.\n", i2c_base, i2c_base_end);
1.113 +
1.114 + /* Obtain CPM and I2C references. */
1.115 +
1.116 + cpm = jz4730_cpm_init(cpm_base);
1.117 + i2c = jz4730_i2c_init(i2c_base, i2c_base_end, cpm, 100000); /* 100 kHz */
1.118 + i2c0 = jz4730_i2c_get_channel(i2c, 0);
1.119 +
1.120 + /* Enable I2C. */
1.121 +
1.122 + jz4730_i2c_enable(i2c0);
1.123 +
1.124 + uint8_t buf[32];
1.125 + unsigned int nwritten;
1.126 +
1.127 + /* Set the clock: 12:34:56 on Saturday 2nd January 2021. */
1.128 +
1.129 + buf[0] = 2; buf[1] = 0x56; buf[2] = 0x34; buf[3] = 0x12; buf[4] = 0x02; buf[5] = 0x06; buf[6] = 0x01; buf[7] = 0x21;
1.130 + nwritten = jz4730_i2c_write(i2c0, 0x51, buf, 8);
1.131 +
1.132 + printf("Written: %d\n", nwritten);
1.133 +
1.134 + /* Issue selection of device register 0. */
1.135 +
1.136 + buf[0] = 0;
1.137 + nwritten = jz4730_i2c_write(i2c0, 0x51, buf, 1);
1.138 +
1.139 + printf("Written: %d\n", nwritten);
1.140 +
1.141 + /* Read the contents of 16 registers. */
1.142 +
1.143 + unsigned int nread = jz4730_i2c_read(i2c0, 0x51, buf, 16);
1.144 +
1.145 + printf("Read: %d\n", nread);
1.146 + for (unsigned int i = 0; i < nread; i++)
1.147 + printf("%02x ", buf[i]);
1.148 + printf("\n");
1.149 +
1.150 + /* Show the interpreted date and time. */
1.151 +
1.152 + rtc_datetime(buf);
1.153 +
1.154 + /* Scan the bus. */
1.155 +
1.156 + printf("Scan I2C0...\n");
1.157 + i2c_scan(i2c0);
1.158 +
1.159 + return 0;
1.160 +}