Repository: jamesbowman/i2cdriver Branch: master Commit: a4bb1abe2175 Files: 114 Total size: 1.1 MB Directory structure: gitextract_xb_7azzl/ ├── .github/ │ └── workflows/ │ └── ci.yml ├── .gitignore ├── .readthedocs.yml ├── .travis.yml ├── LICENSE ├── README.md ├── c/ │ ├── common/ │ │ ├── i2cdriver.c │ │ └── i2cdriver.h │ ├── go │ ├── linux/ │ │ ├── Makefile │ │ ├── Makefile.clang │ │ └── i2c.c │ └── win32/ │ ├── Makefile │ └── i2c.c ├── firmware/ │ ├── README.md │ ├── assets/ │ │ ├── IBMPlexSans-SemiBold.otf │ │ ├── go │ │ └── mkfont.py │ ├── capture.fs │ ├── font.fs │ ├── fontsize.fs │ ├── main.fs │ └── st7735.fs ├── hardware/ │ ├── i2cdriver.brd │ └── i2cdriver.sch ├── nsis/ │ ├── .gitignore │ ├── go.bat │ ├── i2cdriver.nsi │ └── license.txt ├── python/ │ ├── .gitignore │ ├── EDS.py │ ├── MANIFEST │ ├── docs/ │ │ ├── Makefile │ │ ├── conf.py │ │ ├── go │ │ ├── index.rst │ │ └── requirements.txt │ ├── go │ ├── i2cdriver.py │ ├── lm75b.py │ ├── samples/ │ │ ├── EDS-ACCEL.py │ │ ├── EDS-BEEP.py │ │ ├── EDS-CLOCK.py │ │ ├── EDS-DIG2.py │ │ ├── EDS-EPROM.py │ │ ├── EDS-LED.py │ │ ├── EDS-MAGNET.py │ │ ├── EDS-POT.py │ │ ├── EDS-REMOTE.py │ │ ├── EDS-TEMP.py │ │ ├── EDS-color-compass.py │ │ ├── EDS-egg-timer.py │ │ ├── EDS-take-a-ticket.py │ │ ├── bargraph.py │ │ ├── bmp390.py │ │ ├── bno080.py │ │ ├── capture.py │ │ ├── cp437-8x8 │ │ ├── go │ │ ├── ht16k33.py │ │ ├── i2cgui.py │ │ ├── lcd1602.py │ │ ├── led8x8.py │ │ ├── mag3110.py │ │ ├── mux.py │ │ ├── oled.py │ │ ├── pca9685.py │ │ ├── qwiic-joystick.py │ │ ├── qwiic-keypad.py │ │ ├── read-temperature.py │ │ ├── touch.py │ │ └── wii.py │ ├── setup.py │ └── tests/ │ └── accept.py ├── python3/ │ ├── .gitignore │ ├── EDS.py │ ├── README.md │ ├── go │ ├── i2cdriver.py │ ├── pyproject.toml │ └── samples/ │ ├── EDS-ACCEL.py │ ├── EDS-BEEP.py │ ├── EDS-CLOCK.py │ ├── EDS-DIG2.py │ ├── EDS-EPROM.py │ ├── EDS-LED.py │ ├── EDS-MAGNET.py │ ├── EDS-POT.py │ ├── EDS-REMOTE.py │ ├── EDS-TEMP.py │ ├── EDS-color-compass.py │ ├── EDS-egg-timer.py │ ├── EDS-take-a-ticket.py │ ├── bargraph.py │ ├── bmp390.py │ ├── bno080.py │ ├── capture.py │ ├── cp437-8x8 │ ├── go │ ├── ht16k33.py │ ├── i2cgui.py │ ├── lcd1602.py │ ├── led8x8.py │ ├── mag3110.py │ ├── mux.py │ ├── oled.py │ ├── pca9685.py │ ├── qwiic-joystick.py │ ├── qwiic-keypad.py │ ├── read-temperature.py │ ├── tcr.py │ ├── touch.py │ └── wii.py └── testall ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/ci.yml ================================================ name: Lightweight regressions on: [push] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Install Python 3 uses: actions/setup-python@v1 with: python-version: 3.13 - name: Install dependencies run: | python -m pip install --upgrade pip # pip install -r requirements.txt - name: Build and run tests run: ./testall ================================================ FILE: .gitignore ================================================ __pycache__ *.pyc /c/build/ /c/bin/ /c/obj/ ================================================ FILE: .readthedocs.yml ================================================ # .readthedocs.yml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details # Required version: 2 # Build documentation in the docs/ directory with Sphinx sphinx: configuration: python/docs/conf.py # Optionally set the version of Python and requirements required to build your docs python: install: - method: pip path: python formats: all ================================================ FILE: .travis.yml ================================================ language: generic script: ./testall matrix: include: - os: linux sudo: required python: 2.7 install: pip install pyserial env: TOXENV=py27 - os: linux sudo: required python: 3.4 install: pip install pyserial env: TOXENV=py34 - os: linux sudo: required python: 3.5 install: pip install pyserial env: TOXENV=py35 - os: osx sudo: required install: pip install pyserial env: TOXENV=py33 ================================================ FILE: LICENSE ================================================ BSD 3-Clause License Copyright (c) 2019, James Bowman All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================ ![logo](/images/logo.png) [![Build Status](https://travis-ci.org/jamesbowman/i2cdriver.svg?branch=master)](https://travis-ci.org/jamesbowman/i2cdriver) [![Documentation Status](https://readthedocs.org/projects/i2cdriver/badge/?version=latest)](https://i2cdriver.readthedocs.io/en/latest/?badge=latest) I2CDriver is a tool for controlling any I2C device from your PC's USB port, and can also monitor and capture I2C traffic. It connects as a standard USB serial device, so there are no drivers to install. On the main site [i2cdriver.com](https://i2cdriver.com), there are drivers for * Windows/Mac/Linux GUI * Windows/Mac/Linux command-line * Python 2 and 3 * Windows/Mac/Linux C/C++ ![front](/images/hero.jpg) Full documentation is at [i2cdriver.com](http://i2cdriver.com). For developers: How to make a release ------------------------------------- To release Python: cd python3 rm -rf dist/* python -m build twine check dist/* twine upload dist/* To build the Windows installer, you first need to build the two executables ``i2ccl.exe`` and ``i2cgui.exe`` then use an NSIS script to create the installer. On Linux cross-compile ``i2ccl``: cd c make -f win32/Makefile On Windows first make sure that you can run the GUI on the command-line, e.g. python python\samples\i2cgui.py (You may need to install i2cdriver, wxPython and pySerial). Then build the GUI executable using ``pyinstaller``: cd python\samples pyinstaller --onefile --windowed --icon=../../images/i2cdriver.ico i2cgui.py This builds the executable in ``python\samples\dist\i2cgui.exe``. The Windows installer is built with NSIS (Nullsoft Scriptable Install System). Download and install it. Copy the two executables ``i2ccl.exe`` and ``i2cgui.exe`` into ``nsis/``. Then build the installer with NSIS: cd nsis "C:\Program Files\NSIS\makensis.exe" i2cdriver.nsi The script ``go.bat`` in ``nsis`` has an example complete flow. ================================================ FILE: c/common/i2cdriver.c ================================================ #include #include #include #include #include #if !defined(WIN32) #include #include #endif #include #define __STDC_FORMAT_MACROS #include #include #include #include "i2cdriver.h" // **************************** Serial port ******************************** #if defined(WIN32) // { #ifndef NOMINMAX #define NOMINMAX #endif #include void ErrorExit(const char *func_name) { // Retrieve the system error message for the last-error code LPVOID lpMsgBuf; DWORD dw = GetLastError(); FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the error message and exit the process char mm[256]; snprintf(mm, sizeof(mm), "%s failed with error %lu:\n%s", func_name, dw, (char*)lpMsgBuf); MessageBox(NULL, (LPCTSTR)mm, TEXT("Error"), MB_OK); LocalFree(lpMsgBuf); ExitProcess(dw); } HANDLE openSerialPort(const char *portname) { char fullname[10]; const char *fmt; if (portname[0] == 'C') fmt = "\\\\.\\%s"; else fmt = "%s"; snprintf(fullname, sizeof(fullname), fmt, portname); DWORD accessdirection = GENERIC_READ | GENERIC_WRITE; HANDLE hSerial = CreateFile((LPCSTR)fullname, accessdirection, 0, 0, OPEN_EXISTING, 0, 0); if (hSerial == INVALID_HANDLE_VALUE) { ErrorExit("CreateFile"); } DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength=sizeof(dcbSerialParams); if (!GetCommState(hSerial, &dcbSerialParams)) { ErrorExit("GetCommState"); } dcbSerialParams.BaudRate = 1000000; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(hSerial, &dcbSerialParams)) { ErrorExit("SetCommState"); } COMMTIMEOUTS timeouts = {0}; timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant = 50; timeouts.WriteTotalTimeoutMultiplier = 10; if (!SetCommTimeouts(hSerial, &timeouts)) { ErrorExit("SetCommTimeouts"); } return hSerial; } DWORD readFromSerialPort(HANDLE hSerial, uint8_t * buffer, int buffersize) { DWORD dwBytesRead = 0; if (!ReadFile(hSerial, buffer, buffersize, &dwBytesRead, NULL)) { ErrorExit("ReadFile"); } return dwBytesRead; } DWORD writeToSerialPort(HANDLE hSerial, const uint8_t * data, int length) { DWORD dwBytesRead = 0; if (!WriteFile(hSerial, data, length, &dwBytesRead, NULL)) { ErrorExit("WriteFile"); } return dwBytesRead; } void closeSerialPort(HANDLE hSerial) { CloseHandle(hSerial); } #else // }{ #include int openSerialPort(const char *portname) { struct termios Settings; int fd; fd = open(portname, O_RDWR | O_NOCTTY); if (fd == -1) { perror(portname); return -1; } tcgetattr(fd, &Settings); #if defined(__APPLE__) && !defined(B1000000) #include #else cfsetispeed(&Settings, B1000000); cfsetospeed(&Settings, B1000000); #endif cfmakeraw(&Settings); Settings.c_cc[VMIN] = 1; if (tcsetattr(fd, TCSANOW, &Settings) != 0) { perror("Serial settings"); return -1; } #if defined(__APPLE__) && !defined(B1000000) speed_t speed = (speed_t)1000000; ioctl(fd, IOSSIOSPEED, &speed); #endif return fd; } int readFromSerialPort(int fd, uint8_t *b, size_t s) { ssize_t n, t; t = 0; while (t < s) { n = read(fd, b + t, s); if (n > 0) t += n; } #ifdef VERBOSE printf(" READ %d %d: ", (int)s, (int)n); int i; for (i = 0; i < s; i++) printf("%02x ", 0xff & b[i]); printf("\n"); #endif return s; } void writeToSerialPort(int fd, const uint8_t *b, size_t s) { write(fd, b, s); #ifdef VERBOSE printf("WRITE %u: ", (int)s); int i; for (i = 0; i < s; i++) printf("%02x ", 0xff & b[i]); printf("\n"); #endif } void closeSerialPort(HANDLE hSerial) { close((int)hSerial); } #endif // } // ****************************** CCITT CRC ********************************* static const uint16_t crc_table[256] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; static void crc_update(I2CDriver *sd, const uint8_t *data, size_t data_len) { unsigned int tbl_idx; uint16_t crc = sd->e_ccitt_crc; while (data_len--) { tbl_idx = ((crc >> 8) ^ *data) & 0xff; crc = (crc_table[tbl_idx] ^ (crc << 8)) & 0xffff; data++; } sd->e_ccitt_crc = crc; } // ****************************** I2CDriver ********************************* void i2c_connect(I2CDriver *sd, const char* portname) { int i; sd->connected = 0; sd->port = openSerialPort(portname); #if !defined(WIN32) if (sd->port == -1) return; #endif writeToSerialPort(sd->port, (uint8_t*)"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", 64); const uint8_t tests[] = "A\r\n\0xff"; for (i = 0; i < 4; i++) { uint8_t tx[2] = {'e', tests[i]}; writeToSerialPort(sd->port, tx, 2); uint8_t rx[1]; int n = readFromSerialPort(sd->port, rx, 1); if ((n != 1) || (rx[0] != tests[i])) return; } sd->connected = 1; i2c_getstatus(sd); sd->e_ccitt_crc = sd->ccitt_crc; } void i2c_disconnect(I2CDriver *sd) { if (sd->connected) { closeSerialPort(sd->port); sd->port = -1; sd->connected = 0; } } static void charCommand(I2CDriver *sd, char c) { writeToSerialPort(sd->port, (uint8_t*)&c, 1); } static int i2c_ack(I2CDriver *sd) { uint8_t a[1]; if (readFromSerialPort(sd->port, a, 1) != 1) return 0; return (a[0] & 1) != 0; } void i2c_getstatus(I2CDriver *sd) { uint8_t readbuffer[100]; int bytesRead; uint8_t mode[80]; charCommand(sd, '?'); bytesRead = readFromSerialPort(sd->port, readbuffer, 80); readbuffer[bytesRead] = 0; // printf("%d Bytes were read: %.*s\n", bytesRead, bytesRead, readbuffer); sscanf((char*)readbuffer, "[%15s %8s %" SCNu64 " %f %f %f %c %d %d %d %d %x ]", sd->model, sd->serial, &sd->uptime, &sd->voltage_v, &sd->current_ma, &sd->temp_celsius, mode, &sd->sda, &sd->scl, &sd->speed, &sd->pullups, &sd->ccitt_crc ); sd->mode = mode[0]; } bool i2c_setspeed(I2CDriver *sd, unsigned int speed_khz) { uint8_t ch; if (speed_khz == sd->speed) { return true; } switch (speed_khz) { case 100: ch = '1'; break; case 400: ch = '4'; default: return false; } writeToSerialPort(sd->port, &ch, 1); i2c_getstatus(sd); return (bool)(sd->speed == speed_khz); } void i2c_scan(I2CDriver *sd, uint8_t devices[128]) { charCommand(sd, 'd'); (void)readFromSerialPort(sd->port, devices + 8, 112); } uint8_t i2c_reset(I2CDriver *sd) { charCommand(sd, 'x'); uint8_t a[1]; if (readFromSerialPort(sd->port, a, 1) != 1) return 0; return a[0]; } int i2c_start(I2CDriver *sd, uint8_t dev, uint8_t op) { uint8_t start[2] = {'s', (uint8_t)((dev << 1) | op)}; writeToSerialPort(sd->port, start, sizeof(start)); return i2c_ack(sd); } void i2c_stop(I2CDriver *sd) { charCommand(sd, 'p'); } int i2c_write(I2CDriver *sd, const uint8_t bytes[], size_t nn) { size_t i; int ack = 1; for (i = 0; i < nn; i += 64) { size_t len = ((nn - i) < 64) ? (nn - i) : 64; uint8_t cmd[65] = {(uint8_t)(0xc0 + len - 1)}; memcpy(cmd + 1, bytes + i, len); writeToSerialPort(sd->port, cmd, 1 + len); ack = i2c_ack(sd); } crc_update(sd, bytes, nn); return ack; } void i2c_read(I2CDriver *sd, uint8_t bytes[], size_t nn) { size_t i; for (i = 0; i < nn; i += 64) { size_t len = ((nn - i) < 64) ? (nn - i) : 64; uint8_t cmd[1] = {(uint8_t)(0x80 + len - 1)}; writeToSerialPort(sd->port, cmd, 1); readFromSerialPort(sd->port, bytes + i, len); crc_update(sd, bytes + i, len); } } void i2c_monitor(I2CDriver *sd, int enable) { charCommand(sd, enable ? 'm' : '@'); } void i2c_capture(I2CDriver *sd) { printf("Capture started\n"); charCommand(sd, 'c'); uint8_t bytes[1]; int starting = 0; int nbits = 0, bits = 0; while (1) { int i; readFromSerialPort(sd->port, bytes, 1); for (i = 0; i < 2; i++) { int symbol = (i == 0) ? (bytes[0] >> 4) : (bytes[0] & 0xf); switch (symbol) { case 0: break; case 1: starting = 1; break; case 2: printf("STOP\n"); starting = 1; break; case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: bits = (bits << 3) | (symbol & 7); nbits += 3; if (nbits == 9) { int b8 = (bits >> 1), ack = !(bits & 1); if (starting) { starting = 0; printf("START %02x %s", b8 >> 1, (b8 & 1) ? "READ" : "WRITE"); } else { printf("BYTE %02x", b8); } printf(" %s\n", ack ? "ACK" : "NAK"); nbits = 0; bits = 0; } } } } } int i2c_commands(I2CDriver *sd, int argc, char *argv[]) { int i; for (i = 0; i < argc; i++) { char *token = argv[i]; // printf("token [%s]\n", token); if (strlen(token) != 1) goto badcommand; switch (token[0]) { case 'i': i2c_getstatus(sd); printf("uptime %" SCNu64" %.3f V %.0f mA %.1f C SDA=%d SCL=%d speed=%d kHz\n", sd->uptime, sd->voltage_v, sd->current_ma, sd->temp_celsius, sd->sda, sd->scl, sd->speed ); break; case 'x': { uint8_t sda_scl = i2c_reset(sd); printf("Bus reset. SDA = %d, SCL = %d\n", 1 & (sda_scl >> 1), 1 & sda_scl); } break; case 'd': { uint8_t devices[128]; int i; i2c_scan(sd, devices); printf("\n"); for (i = 8; i < 0x78; i++) { if (devices[i] == '1') printf("%02x ", i); else printf("-- "); if ((i % 8) == 7) printf("\n"); } printf("\n"); } break; case 'w': { token = argv[++i]; unsigned int dev = strtol(token, NULL, 0); token = argv[++i]; uint8_t bytes[8192]; char *endptr = token; size_t nn = 0; while (nn < sizeof(bytes)) { bytes[nn++] = strtol(endptr, &endptr, 0); if (*endptr == '\0') break; if (*endptr != ',') { fprintf(stderr, "Invalid bytes '%s'\n", token); return 1; } endptr++; } i2c_start(sd, dev, 0); i2c_write(sd, bytes, nn); } break; case 'r': { token = argv[++i]; unsigned int dev = strtol(token, NULL, 0); token = argv[++i]; size_t nn = strtol(token, NULL, 0); uint8_t bytes[8192]; i2c_start(sd, dev, 1); i2c_read(sd, bytes, nn); i2c_stop(sd); size_t i; for (i = 0; i < nn; i++) printf("%s0x%02x", i ? "," : "", 0xff & bytes[i]); printf("\n"); } break; case 'p': i2c_stop(sd); break; case 'm': { char line[100]; i2c_monitor(sd, 1); printf("[Hit return to exit monitor mode]\n"); fgets(line, sizeof(line) - 1, stdin); i2c_monitor(sd, 0); } break; case 'c': { i2c_capture(sd); } break; default: badcommand: fprintf(stderr, "Bad command '%s'\n", token); fprintf(stderr, "\n"); fprintf(stderr, "Commands are:"); fprintf(stderr, "\n"); fprintf(stderr, " i display status information (uptime, voltage, current, temperature)\n"); fprintf(stderr, " x I2C bus reset\n"); fprintf(stderr, " d device scan\n"); fprintf(stderr, " w dev write bytes to I2C device dev\n"); fprintf(stderr, " p send a STOP\n"); fprintf(stderr, " r dev N read N bytes from I2C device dev, then STOP\n"); fprintf(stderr, " m enter I2C bus monitor mode\n"); fprintf(stderr, " c enter I2C bus capture mode\n"); fprintf(stderr, "\n"); return 1; } } return 0; } ================================================ FILE: c/common/i2cdriver.h ================================================ #ifndef I2CDRIVER_H #define I2CDRIVER_H #include #include #if defined(WIN32) #include #else #define HANDLE int #endif typedef struct { int connected; // Set to 1 when connected HANDLE port; char model[16], serial[9]; // Serial number of USB device uint64_t uptime; // time since boot (seconds) float voltage_v, // USB voltage (Volts) current_ma, // device current (mA) temp_celsius; // temperature (C) unsigned int mode; // I2C 'I' or bitbang 'B' mode unsigned int sda; // SDA state, 0 or 1 unsigned int scl; // SCL state, 0 or 1 unsigned int speed; // I2C line speed (in kHz) unsigned int pullups; // pullup state (6 bits, 1=enabled) unsigned int ccitt_crc, // Hardware CCITT CRC e_ccitt_crc; // Host CCITT CRC, should match } I2CDriver; void i2c_connect(I2CDriver *sd, const char* portname); void i2c_disconnect(I2CDriver *sd); void i2c_getstatus(I2CDriver *sd); int i2c_write(I2CDriver *sd, const uint8_t bytes[], size_t nn); void i2c_read(I2CDriver *sd, uint8_t bytes[], size_t nn); int i2c_start(I2CDriver *sd, uint8_t dev, uint8_t op); void i2c_stop(I2CDriver *sd); bool i2c_setspeed(I2CDriver *sd, unsigned int kbaud); void i2c_monitor(I2CDriver *sd, int enable); void i2c_capture(I2CDriver *sd); int i2c_commands(I2CDriver *sd, int argc, char *argv[]); #endif ================================================ FILE: c/go ================================================ set -e rm -rf build/* make -f linux/Makefile # build/i2ccl /dev/ttyUSB0 i d # build/i2ccl /dev/ttyUSB0 w 0x48 3 r 0x48 2 make -f win32/Makefile # cp build/spicl.exe /data/win10/ # # rm -f win32gui/obj/* win32gui/bin/Win32App.exe # make -C win32gui/ CHARSET=ANSI # cp win32gui/bin/Win32App.exe /data/win10/spigui.exe # # ./mk-nsis /data/win10/nsis ================================================ FILE: c/linux/Makefile ================================================ CFLAGS += -I common -Wall -Wpointer-sign # -Werror all: build/i2ccl install: all cp build/i2ccl /usr/local/bin build/i2ccl: linux/i2c.c common/i2cdriver.c mkdir -p build/ $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $^ ================================================ FILE: c/linux/Makefile.clang ================================================ CC=clang CFLAGS += -I common -Wall -Wpointer-sign -xc++ -std=c++17 # -Werror all: build/i2ccl install: all cp build/i2ccl /usr/local/bin build/i2ccl: linux/i2c.c common/i2cdriver.c mkdir -p build/ $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $^ ================================================ FILE: c/linux/i2c.c ================================================ #include #include #include "i2cdriver.h" int main(int argc, char *argv[]) { I2CDriver i2c; if (argc < 2) { printf("Usage: i2ccl \n"); exit(1); } else { i2c_connect(&i2c, argv[1]); if (!i2c.connected) exit(1); return i2c_commands(&i2c, argc - 2, argv + 2); } } ================================================ FILE: c/win32/Makefile ================================================ CC = /usr/bin/i686-w64-mingw32-g++ CFLAGS += -I common -static-libgcc -static-libstdc++ all: build/i2ccl.exe build/i2ccl.exe: win32/i2c.c common/i2cdriver.c mkdir -p build/ $(CC) -o $@ $(CPPFLAGS) $(CFLAGS) $^ ================================================ FILE: c/win32/i2c.c ================================================ #include #include #include "i2cdriver.h" int main(int argc, char *argv[]) { I2CDriver sd; if (argc < 2) { printf("Usage: i2ccl \n"); exit(1); } else { i2c_connect(&sd, argv[1]); if (!sd.connected) exit(1); return i2c_commands(&sd, argc - 2, argv + 2); } } ================================================ FILE: firmware/README.md ================================================ This is the firmware for the I2CDriver. It uses the [MyForth](http://www.kiblerelectronics.com/myf/myf.shtml) compiler written by Charley Shattuck and Bob Nash. To compile the fonts go into ``assets`` and run ``mkfont.py``. This builds the font sources in ``fonts.fs`` ================================================ FILE: firmware/assets/go ================================================ set -e python2 mkfont.py ================================================ FILE: firmware/assets/mkfont.py ================================================ #!/usr/bin/python # -*- coding: utf-8 -*- import sys from PIL import Image, ImageDraw, ImageFont import numpy as np import struct import random def rand(n): return random.randrange(n) def as565(im): """ Return RGB565 of im """ (r,g,b) = [np.array(c).astype(np.uint16) for c in im.split()] def s(x, n): return x * (2 ** n - 1) / 255 return (s(b, 5) << 11) | (s(g, 6) << 5) | s(r, 5) def c3(rgb): return (16 * (0xf & (rgb >> 8)), 16 * (0xf & (rgb >> 4)), 16 * (0xf & (rgb >> 0))) font2 = ImageFont.truetype("IBMPlexSans-SemiBold.otf", 13) fontSP = ImageFont.truetype("pf_ronda_seven_bold.ttf", 8) def pad2(s): if len(s) % 2: s.append(s[0]) return s def rfont2(c): im = Image.new("L", (128, 160)) dr = ImageDraw.Draw(im) dr.text((10,40), c, font=font2, fill=255) # im.save("out.png") extents = im.getbbox() assert 10 <= extents[0] assert 45 <= extents[1] if c in "0123456789": extents = (0, 0, 10 + 8, 45 + 9) im = im.crop((10, 45) + extents[2:]) (w,h) = im.size nyb = pad2((np.array(im).astype(int).flatten() * 15 / 255).tolist()) return [w,h] + nyb def rf(c, font): im = Image.new("L", (128, 160)) dr = ImageDraw.Draw(im) dr.text((10,40), c, font=font, fill=255) # im.save("out.png") extents = im.getbbox() im = im.crop(extents) (w,h) = im.size nyb = (np.array(im).astype(int).flatten() * 15 / 255).tolist() return [w,h] + nyb fs = open("../font.fs", "wt") fb = 0 if __name__ == '__main__': fs.write('here constant tplan\n') fs.write('%d , %d , $%x%x , $%x , ," %s"\n' % (60, 0, 0xf, 0xf, 0xf, "V")) fb += 5 + len("V") # fs.write("[ %d ]\n" % fb) fs.write('%d , %d , $%x%x , $%x , ," %s"\n' % (108, 0, 0xf, 0xf, 0xf, "mA")) fb += 5 + len("mA") # fs.write("[ %d ]\n" % fb) fs.write('0 ,\n') fb += 1 # im.save("out.png") uniq = "".join(sorted(set("0123456789.mAVDMCS"))) f2 = sum([rfont2(c) for c in uniq], []) print "font2 %s takes %d bytes" % (uniq, len(f2) / 2) def nybbles(nn): s = len(nn) assert s % 2 == 0 b = ["$%x%x ," % tuple(nn[i:i+2]) for i in range(0, s, 2)] return b fs.write('here constant font\n') for c in uniq: bb = nybbles(rfont2(c)) print >>fs, "'%s' , " % c, " ".join(bb) fb += 1 + len(bb) # See http://angband.pl/font/tinyfont.html fs.write("\nhere constant micro\n") if 1: tiny = Image.open("hex4x5.png").convert("L") for i in range(16): x = 5 * i im = tiny.crop((x, 0, x + 4, 5)) rim = im.transpose(Image.ROTATE_90) ch = ((np.array(rim)).flatten() * 15.99 / 255).astype(np.uint8).tolist() fs.write(" ".join(nybbles(ch)) + "\n") fb += len(ch) / 2 if 1: # Image.open("arrow.png").transpose(Image.FLIP_LEFT_RIGHT).save("larrow.png") for n in ("symbol-s", "symbol-p", "symbol-b", "arrow", "larrow", "dot", "label-sda", "label-scl"): im = Image.open(n + ".png").convert("L") if n.startswith("label-"): im = im.point([0] + 254 * [64] + [255]) rim = im.transpose(Image.ROTATE_90) (w,h) = rim.size ch = [w,h] + pad2(((np.array(rim)).flatten() * 15.99 / 255).astype(np.uint8).tolist()) fs.write("here constant %s \n" % n) fs.write(" ".join(nybbles(ch)) + "\n") fb += len(ch) / 2 if 1: w = 72 gpng = "plasma.png" grad = Image.open(gpng).convert("RGB").resize((w, 1), Image.BILINEAR).load() fs.write("\nHERE constant grad\n") for x in range(w): (r,g,b) = grad[x,0] r = (r * 15) // 255 g = (g * 15) // 255 b = (b * 15) // 255 fs.write('$%x%x , $%x ,\n' % (r, g, b)) fb += 2 * w fs.close() fs = open("../fontsize.fs", "wt") fs.write("&%d constant FONTDATA_SIZE\n" % fb) fs.close() ================================================ FILE: firmware/capture.fs ================================================ here constant CAPTURE-START [ : fake ( a - u ) dup 0= ] here [ and or ; ] :m :: ( - ) [ >in @ label >in ! create ] here [ , hide does> @ ] m; \ jump if bit is 0 or 1 ( addr bit ) :m j1 ( addr bit ) [ swap fake swap ] 0=until. m; :m j0 ( addr bit ) [ swap fake swap ] until. m; :m j ( addr ) fake again m; :m tx SBUF0 (#!) clra TMR3H (#!) m; :m SDA0 ( a ) SDA j0 m; :m SDA1 ( a ) SDA j1 m; fwd L00.0 fwd L00.1 fwd L00.2 fwd H00.0 fwd H00.1 fwd H00.2 fwd HS fwd HP fwd LP fwd LS :m escape RI0 if. RI0 clr ; then m; :: L11 begin LS SDA0 SCL 0=until. :: Lidle begin begin SDA until. SCL until. L11 j :: L10.0 3 .t set begin L00.0 SDA0 SCL until. begin LS SDA0 SCL 0=until. 2 .t set :: L10.1 begin L00.1 SDA0 SCL until. begin LS SDA0 SCL 0=until. 1 .t set :: L10.2 begin L00.2 SDA0 SCL until. begin LS SDA0 SCL 0=until. 0 .t set tx :: H10.0 7 .t set :: klak begin H00.0 SDA0 SCL until. begin HS SDA0 SCL 0=until. 6 .t set :: H10.1 begin H00.1 SDA0 SCL until. begin HS SDA0 SCL 0=until. 5 .t set :: H10.2 begin H00.2 SDA0 SCL until. begin HS SDA0 SCL 0=until. 4 .t set L10.0 j :: LS $f0 # and $01 # ior tx ( start ) :: LS2 begin HP SDA1 SCL 0=until. H00.0 j :: HS $10 (#) ( start ) :: HS2 begin LP SDA1 SCL 0=until. :: L00.0 3 .t set begin L10.0 SDA1 SCL until. begin LP SDA1 SCL 0=until. :: L00.1 begin L10.1 SDA1 SCL until. begin LP SDA1 SCL 0=until. :: L00.2 begin L10.2 SDA1 SCL until. begin LP SDA1 SCL 0=until. tx :: H00.0 7 .t set begin H10.0 SDA1 SCL until. begin HP SDA1 SCL 0=until. :: H00.1 begin H10.1 SDA1 SCL until. begin HP SDA1 SCL 0=until. :: H00.2 begin H10.2 SDA1 SCL until. begin HP SDA1 SCL 0=until. L00.0 j :: HP $20 (#) \ L11 j begin SDA 0=until. escape HS2 j : (warm) :: H11 begin HS SDA0 SCL 0=until. :: Hidle begin begin SDA until. SCL until. H11 j :: LP $f0 # and $02 # ior tx \ H11 j begin SDA 0=until. escape LS2 j : /timer3 $80 # EIE1 ior! \ Timer 3 interrupt enable ; : timer3\ $80 ~# EIE1 and! \ Timer 3 interrupt disable ; :m timer3 SBUF0 (#!) clra $7f # TMR3CN and! RI0 if. RI0 clr [ sp dec ] [ sp dec ] then [ reti ] m; : capture [ IE push ] [ ET2 clr ] \ Timer 2 interrupt disable [ ES0 clr ] \ UART interrupt disable \i2chw [ clra ] [ FL1 set ] t3+ (warm) t3- [ FL1 clr ] /i2chw [ IE pop ] ; \ This code all runs in register bank 1: \ 0 scratch for heatmap \ 1 log \ 2 \ 3 prev cmd \ 4 constant 72, for heatmap \ 5 \ 6 \ 7 caller acc save \ \ FL0 set means this is an address byte fwd M00.0 fwd M10.0 fwd M10.1 fwd M10.2 fwd M10.3 fwd M10.4 fwd M10.5 fwd M10.6 fwd M10.7 fwd M10.8 fwd Mt fwd MP :m (l!) $f3 , m; :m (log!) $f3 , a+ m; :m wrap $7f # 9 and! m; :m heat \ byte is in t FL0 if. setc 2/' 0 (#!) 4 (#@) $f2 , then m; :m escape 7 (#@) [ dirty set PSW pop reti ] m; :: MP $00 (#) (log!) $01 (#) (log!) wrap escape begin SDA 0=until. : (mismatch) :: Mt begin MP SDA1 SCL 0=until. $82 # 3 #! FL0 set M00.0 j :: M00.6 begin M10.6 SDA1 SCL until. begin MP SDA1 SCL 0=until. :: M00.7 begin M10.7 SDA1 SCL until. begin MP SDA1 SCL 0=until. (l!) :: M00.8 begin M10.8 SDA1 SCL until. begin MP SDA1 SCL 0=until. heat a+ 3 (#@) (l!) a+ wrap $83 # 3 #! FL0 clr M00.0 j :: M10.6 begin M00.6 SDA0 SCL until. begin Mt SDA0 SCL 0=until. 1 .t set :: M10.7 begin M00.7 SDA0 SCL until. begin Mt SDA0 SCL 0=until. 1+ (l!) :: M10.8 begin M00.8 SDA0 SCL until. begin Mt SDA0 SCL 0=until. a+ 3 (#@) $7f # and (l!) a+ wrap $83 # 3 #! FL0 clr M10.0 j :: MP3 MP j :: Mt3 Mt j :: M00.3 begin M10.3 SDA1 SCL until. begin MP3 SDA1 SCL 0=until. :: M00.4 begin M10.4 SDA1 SCL until. begin MP3 SDA1 SCL 0=until. :: M00.5 begin M10.5 SDA1 SCL until. begin MP3 SDA1 SCL 0=until. M00.6 j :: M10.3 begin M00.3 SDA0 SCL until. begin Mt3 SDA0 SCL 0=until. 4 .t set :: M10.4 begin M00.4 SDA0 SCL until. begin Mt3 SDA0 SCL 0=until. 3 .t set :: M10.5 begin M00.5 SDA0 SCL until. begin Mt3 SDA0 SCL 0=until. 2 .t set M10.6 j :: MP0 MP j :: Mt0 Mt j : (warm) :: M00.0 clra begin M10.0 SDA1 SCL until. begin MP0 SDA1 SCL 0=until. :: M00.1 begin M10.1 SDA1 SCL until. begin MP0 SDA1 SCL 0=until. :: M00.2 begin M10.2 SDA1 SCL until. begin MP0 SDA1 SCL 0=until. M00.3 j :: M10.0 clra begin M00.0 SDA0 SCL until. begin Mt0 SDA0 SCL 0=until. 7 .t set :: M10.1 begin M00.1 SDA0 SCL until. begin Mt0 SDA0 SCL 0=until. 6 .t set :: M10.2 begin M00.2 SDA0 SCL until. begin Mt0 SDA0 SCL 0=until. 5 .t set M10.3 j : /monitor [ ET2 clr ] \ Timer 2 interrupt disable [ ES0 clr ] \ UART interrupt disable \i2chw t3i- t3+ \ Timer3 running, no intr %00000100 # P0MASK #! %00000100 # P0MAT #! \ SDA high %00010000 # P1MASK #! %00010000 # P1MAT #! \ SCL high \ constants in registers 72 # [ 4 8 + ] #! $02 # EIE1 ior! \ EMAT ; : \monitor $02 ~# EIE1 and! \ EMAT off [ ET2 set ] \ Timer 2 interrupt enable [ ES0 set ] \ UART interrupt enable t3i+ t3- \ Timer3 stopped, intr /i2chw ; :m mismatch [ PSW push RS0 set ] 7 (#!) Mt j m; here [ CAPTURE-START xor 11 rshift 0<> [IF] cr .( Capture block cannot cross a 2K boundary) abort [THEN] ] ================================================ FILE: firmware/font.fs ================================================ here constant tplan 60 , 0 , $ff , $f , ," V" 108 , 0 , $ff , $f , ," mA" 0 , here constant font '.' , $49 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $03 , $20 , $2f , $e0 , $0c , $b0 , '0' , $89 , $01 , $9d , $d8 , $00 , $0c , $fc , $df , $90 , $4f , $b0 , $0d , $e1 , $7f , $70 , $0b , $f4 , $9f , $70 , $0a , $f5 , $7f , $70 , $0b , $f4 , $4f , $a0 , $0d , $e1 , $0c , $fb , $cf , $90 , $01 , $ad , $d8 , $00 , '1' , $89 , $00 , $af , $f7 , $00 , $09 , $fd , $f7 , $00 , $6f , $a7 , $f7 , $00 , $07 , $07 , $f7 , $00 , $00 , $07 , $f7 , $00 , $00 , $07 , $f7 , $00 , $00 , $07 , $f7 , $00 , $09 , $9c , $fc , $95 , $0e , $ff , $ff , $f8 , '2' , $89 , $02 , $ae , $d8 , $00 , $1d , $fc , $ef , $90 , $3b , $70 , $3f , $e0 , $00 , $00 , $4f , $c0 , $00 , $02 , $de , $40 , $00 , $4d , $e4 , $00 , $06 , $ed , $30 , $00 , $4f , $fb , $aa , $a2 , $5f , $ff , $ff , $f3 , '3' , $89 , $04 , $ce , $d7 , $00 , $3e , $eb , $df , $80 , $05 , $10 , $5f , $b0 , $00 , $6b , $dd , $30 , $00 , $9f , $fc , $20 , $00 , $00 , $6f , $c0 , $2a , $10 , $2f , $e0 , $8f , $eb , $df , $80 , $07 , $ce , $c7 , $00 , '4' , $89 , $00 , $05 , $ff , $40 , $00 , $1d , $ff , $40 , $00 , $8e , $cf , $40 , $03 , $e8 , $9f , $40 , $0c , $d0 , $9f , $40 , $6f , $50 , $9f , $40 , $bf , $ff , $ff , $f7 , $69 , $99 , $cf , $a4 , $00 , $00 , $9f , $40 , '5' , $89 , $0c , $ff , $ff , $c0 , $0d , $eb , $bb , $90 , $0e , $a0 , $00 , $00 , $0f , $aa , $eb , $20 , $1f , $fb , $df , $d0 , $02 , $20 , $0d , $f3 , $07 , $40 , $0d , $f2 , $2e , $eb , $df , $b0 , $03 , $be , $d8 , $10 , '6' , $89 , $00 , $1a , $fc , $10 , $00 , $cf , $90 , $00 , $09 , $f8 , $00 , $00 , $1e , $da , $eb , $30 , $5f , $fb , $bf , $d0 , $7f , $a0 , $0c , $f4 , $5f , $a0 , $0c , $f3 , $0c , $eb , $bf , $b0 , $01 , $ad , $d9 , $10 , '7' , $89 , $5f , $ff , $ff , $f2 , $5f , $ba , $ae , $f2 , $5f , $50 , $3f , $c0 , $14 , $10 , $9f , $50 , $00 , $01 , $ee , $00 , $00 , $07 , $f8 , $00 , $00 , $0d , $e2 , $00 , $00 , $5f , $a0 , $00 , $00 , $bf , $40 , $00 , '8' , $89 , $03 , $be , $d9 , $10 , $1e , $ea , $bf , $c0 , $2f , $a0 , $0d , $e0 , $09 , $e9 , $ae , $60 , $06 , $ef , $fd , $40 , $5f , $b1 , $2d , $e2 , $7f , $80 , $0c , $f4 , $2e , $ea , $bf , $d0 , $03 , $be , $da , $20 , '9' , $89 , $02 , $ae , $d8 , $00 , $1d , $eb , $cf , $90 , $6f , $90 , $0d , $f1 , $7f , $80 , $0d , $f3 , $3e , $ea , $bf , $f2 , $05 , $ce , $af , $d0 , $00 , $00 , $af , $50 , $00 , $1b , $f9 , $00 , $02 , $df , $80 , $00 , 'A' , $99 , $00 , $0e , $fa , $00 , $00 , $04 , $ff , $e1 , $00 , $00 , $9f , $9f , $50 , $00 , $0e , $c2 , $fb , $00 , $05 , $f7 , $0c , $e1 , $00 , $af , $ff , $ff , $60 , $1e , $eb , $bb , $fb , $06 , $f8 , $00 , $0d , $f1 , $bf , $40 , $00 , $8f , $70 , 'C' , $99 , $00 , $5b , $ec , $70 , $00 , $6f , $ec , $ef , $80 , $1e , $e2 , $01 , $c7 , $04 , $fa , $00 , $00 , $00 , $6f , $90 , $00 , $00 , $04 , $fa , $00 , $00 , $00 , $1e , $e1 , $01 , $d8 , $00 , $7f , $ec , $ef , $80 , $00 , $6c , $ec , $60 , $00 , 'D' , $99 , $1f , $ff , $eb , $50 , $01 , $fe , $cc , $ef , $60 , $1f , $d0 , $02 , $ee , $01 , $fd , $00 , $0b , $f3 , $1f , $d0 , $00 , $af , $51 , $fd , $00 , $0b , $f3 , $1f , $d0 , $01 , $ee , $11 , $fe , $bc , $ef , $60 , $1f , $ff , $eb , $50 , $01 , 'M' , $a9 , $1f , $f5 , $00 , $0a , $fa , $1f , $fc , $00 , $3f , $fa , $1f , $ff , $60 , $bf , $fa , $1f , $dd , $d5 , $fb , $fa , $1f , $c6 , $fe , $e4 , $fa , $1f , $c0 , $cf , $63 , $fa , $1f , $c0 , $4d , $03 , $fa , $1f , $c0 , $02 , $03 , $fa , $1f , $c0 , $00 , $03 , $fa , 'S' , $89 , $02 , $ad , $da , $20 , $0d , $fd , $df , $e1 , $4f , $b0 , $04 , $30 , $2e , $e8 , $51 , $00 , $05 , $df , $ff , $80 , $00 , $02 , $5d , $f4 , $08 , $30 , $0a , $f5 , $5f , $fd , $df , $d1 , $04 , $be , $da , $20 , 'V' , $99 , $cf , $30 , $00 , $de , $17 , $f8 , $00 , $3f , $b0 , $2f , $d0 , $08 , $f6 , $00 , $cf , $20 , $de , $10 , $06 , $f7 , $2f , $b0 , $00 , $1f , $b6 , $f6 , $00 , $00 , $be , $ce , $10 , $00 , $06 , $ff , $a0 , $00 , $00 , $1e , $f5 , $00 , $0c , 'm' , $b9 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $00 , $2f , $ba , $ea , $1a , $ea , $12 , $ff , $bd , $fe , $bd , $f8 , $2f , $c0 , $3f , $c0 , $3f , $b2 , $fb , $02 , $fb , $02 , $fc , $2f , $b0 , $2f , $b0 , $2f , $c2 , $fb , $02 , $fb , $02 , $fc , $2f , $b0 , $2f , $b0 , $2f , $c0 , here constant micro $4f , $ff , $4f , $00 , $0f , $f0 , $00 , $f4 , $ff , $f4 , $00 , $00 , $0f , $ff , $ff , $f0 , $00 , $00 , $00 , $00 , $4f , $40 , $ff , $0f , $0f , $f0 , $f0 , $ff , $04 , $ff , $4f , $4f , $4f , $0f , $0f , $f0 , $f0 , $ff , $04 , $0f , $ff , $ff , $f0 , $0f , $00 , $00 , $f0 , $0f , $ff , $00 , $f0 , $4f , $4f , $0f , $0f , $f0 , $f0 , $ff , $ff , $0f , $40 , $4f , $4f , $0f , $0f , $f0 , $f0 , $f4 , $ff , $f4 , $ff , $00 , $0f , $0f , $00 , $f0 , $0f , $ff , $00 , $00 , $4f , $4f , $4f , $0f , $0f , $f0 , $f0 , $f4 , $f4 , $f4 , $4f , $ff , $4f , $0f , $0f , $f0 , $f0 , $f4 , $f4 , $04 , $4f , $ff , $ff , $0f , $00 , $f0 , $f0 , $04 , $ff , $ff , $4f , $4f , $4f , $0f , $0f , $f0 , $f0 , $ff , $ff , $ff , $4f , $0f , $4f , $00 , $0f , $f0 , $00 , $f4 , $ff , $f4 , $4f , $ff , $4f , $00 , $0f , $f0 , $00 , $ff , $ff , $ff , $00 , $00 , $0f , $0f , $0f , $f0 , $f0 , $ff , $ff , $ff , $00 , $00 , $0f , $0f , $00 , $f0 , $f0 , $0f , $ff , $ff , here constant symbol-s $bc , $00 , $17 , $ce , $d8 , $20 , $00 , $2b , $ff , $ff , $fc , $30 , $0a , $ff , $ff , $ff , $fb , $15 , $fd , $0f , $d0 , $0d , $f6 , $af , $00 , $f0 , $00 , $0f , $cc , $f0 , $ff , $0f , $f0 , $fe , $cf , $0f , $f0 , $ff , $0f , $e9 , $f0 , $00 , $0f , $00 , $fb , $4e , $d0 , $0d , $f0 , $df , $60 , $9f , $ff , $ff , $ff , $a1 , $01 , $9f , $ff , $ff , $b2 , $00 , $00 , $5b , $db , $61 , $00 , here constant symbol-p $bc , $00 , $17 , $ce , $d8 , $20 , $00 , $2b , $ff , $ff , $fc , $30 , $0a , $ff , $ff , $ff , $fb , $15 , $fd , $00 , $df , $ff , $f6 , $af , $00 , $00 , $ff , $ff , $cc , $f0 , $ff , $0f , $ff , $fe , $cf , $0f , $f0 , $ff , $ff , $e9 , $f0 , $00 , $00 , $00 , $fb , $4e , $00 , $00 , $00 , $0f , $60 , $9f , $ff , $ff , $ff , $a1 , $01 , $9f , $ff , $ff , $b2 , $00 , $00 , $5b , $db , $61 , $00 , here constant symbol-b $bc , $00 , $17 , $ce , $d8 , $20 , $00 , $2b , $ff , $ff , $fc , $30 , $0a , $ff , $ff , $ff , $fb , $15 , $ff , $ff , $ff , $ff , $f6 , $af , $ff , $ff , $ff , $ff , $cc , $f0 , $00 , $00 , $f0 , $fe , $cf , $00 , $00 , $0f , $0f , $e9 , $ff , $ff , $ff , $ff , $fb , $4e , $ff , $ff , $ff , $ff , $60 , $9f , $ff , $ff , $ff , $a1 , $01 , $9f , $ff , $ff , $b2 , $00 , $00 , $5b , $db , $61 , $00 , here constant arrow $35 , $08 , $03 , $b3 , $8f , $8b , $fb , $ef , $e0 , here constant larrow $35 , $ef , $eb , $fb , $8f , $83 , $b3 , $08 , $0e , here constant dot $44 , $4c , $d5 , $bf , $fd , $bf , $fc , $3b , $b4 , here constant label-sda $810 , $f0 , $00 , $00 , $00 , $f0 , $00 , $00 , $00 , $f0 , $4f , $ff , $f0 , $f0 , $f0 , $f0 , $00 , $f0 , $f0 , $f0 , $00 , $f0 , $4f , $ff , $f0 , $f0 , $00 , $00 , $00 , $f0 , $4f , $ff , $40 , $f0 , $f0 , $00 , $f0 , $f0 , $f0 , $00 , $f0 , $f0 , $ff , $ff , $f0 , $f0 , $00 , $00 , $00 , $f0 , $f0 , $4f , $40 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $4f , $40 , $f0 , here constant label-scl $810 , $f0 , $00 , $00 , $00 , $f0 , $00 , $00 , $00 , $f0 , $00 , $00 , $00 , $f0 , $00 , $00 , $f0 , $f0 , $00 , $00 , $f0 , $f0 , $ff , $ff , $f0 , $f0 , $00 , $00 , $00 , $f0 , $4f , $0f , $40 , $f0 , $f0 , $00 , $f0 , $f0 , $f0 , $00 , $f0 , $f0 , $4f , $ff , $40 , $f0 , $00 , $00 , $00 , $f0 , $f0 , $4f , $40 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $f0 , $4f , $40 , $f0 , HERE constant grad $00 , $7 , $10 , $8 , $10 , $8 , $20 , $8 , $20 , $8 , $30 , $8 , $30 , $9 , $30 , $9 , $40 , $9 , $40 , $9 , $40 , $9 , $50 , $9 , $50 , $9 , $50 , $9 , $60 , $9 , $60 , $9 , $60 , $9 , $70 , $9 , $70 , $9 , $70 , $9 , $70 , $9 , $80 , $9 , $80 , $9 , $81 , $9 , $91 , $9 , $91 , $9 , $91 , $8 , $92 , $8 , $a2 , $8 , $a2 , $8 , $a2 , $8 , $a2 , $8 , $b3 , $7 , $b3 , $7 , $b3 , $7 , $b3 , $7 , $b4 , $7 , $c4 , $6 , $c4 , $6 , $c4 , $6 , $c5 , $6 , $c5 , $6 , $d5 , $5 , $d5 , $5 , $d6 , $5 , $d6 , $5 , $d6 , $5 , $d6 , $5 , $d7 , $4 , $e7 , $4 , $e7 , $4 , $e7 , $4 , $e8 , $4 , $e8 , $3 , $e8 , $3 , $e9 , $3 , $e9 , $3 , $e9 , $3 , $e9 , $3 , $ea , $2 , $ea , $2 , $ea , $2 , $eb , $2 , $eb , $2 , $eb , $2 , $ec , $2 , $ec , $2 , $ec , $2 , $ed , $2 , $ed , $2 , $ed , $2 , $ee , $2 , ================================================ FILE: firmware/fontsize.fs ================================================ &1385 constant FONTDATA_SIZE ================================================ FILE: firmware/main.fs ================================================ 24500000 constant SYSCLK 0 constant CLOSEUP \ P0.0 SDA 2K2 \ P0.1 SDA 4K3 \ P0.2 SDA \ P0.3 SDA 4K7 \ P0.4 RX \ P0.5 TX \ P0.6 A.V \ P0.7 A.C \ P1.0 RS/DC \ P1.1 DATA \ P1.2 CLOCK \ P1.3 RESET \ P1.4 SCL \ P1.5 SCL 2K2 \ P1.6 SCL 4K3 \ P2.0 SCL 4K7 0 [if] There are 3 threads: 1000Hz tick. Increments the BCD milliscond timer. Timer 2 interrupt. UART/SPI service. Runs the transport. UART and SPI interrupts. [DPTR, R0] graphics. renders the main image. Main thread. [DPTR, R0-7] ADC drive. Runs ADC conversions, stores results in adc-. ADC end of conversion interrupt. [then] [ : ," '"' parse dup ] , [ bounds do i c@ ] , [ loop ; ] :m t3+ %00000100 # TMR3CN #! m; \ Timer 3 enable :m t3- %00000000 # TMR3CN #! m; \ Timer 3 enable :m t3i+ $80 # EIE1 ior! m; \ Timer 3 interrupt enable :m t3i- $80 ~# EIE1 and! m; \ Timer 3 interrupt disable $0090 org : 2dup |over : over |over ; : tuck swap over ; :m p>r [ dpl push dph push ] m; : r>p [ dph pop dpl pop ] ; \ MUST be followed by ; : @p |@p ; : @p+ |@p+ ; : * |* ; : um* |um* ; :m #+! [ dup add ] #! m; : dnegate swap invert swap invert : d1+ swap 1 # + swap 0 # +' ; : d+ push swap push + pop pop +' ; :m d2/ clrc 2/' swap 2/' swap m; : - negate + ; : twist ( a b c d -- a c b d ) push swap pop ; :m /uart REN0 set \ Receive enable TR1 set $20 # TMOD #! $18 # CKCON #! \ Use system clock (T1,T2) [ SYSCLK 2/ 1000000 / negate ] # TH1 #! \ speed ES0 set m; [ : array create , does> @ + ; ] $10 cpuORG $09 constant log \ logging ring pointer cpuHERE constant tempr 2 cpuALLOT \ temperature ADC cpuHERE constant currr 2 cpuALLOT \ current ADC cpuHERE constant currd 2 cpuALLOT \ decimal cpuHERE constant slowc 1 cpuALLOT \ slow refresh counter cpuHERE constant charc 1 cpuALLOT \ character counter cpuHERE constant convs 1 cpuALLOT \ converter state (2 bit) cpuHERE constant other 1 cpuALLOT \ context SP save cpuHERE array clock 6 cpuALLOT cpuHERE $20 <> throw cpuHERE constant flags 1 cpuALLOT $00 constant dirty $01 constant prev. $02 constant talked. $03 constant ptalked. $04 constant fade. $05 constant risen. $06 constant modechange. $07 constant timeout cpuHERE constant ftemp 1 cpuALLOT $08 constant f.0 $09 constant f.1 $0a constant f.2 $0b constant f.3 $0c constant f.4 $0d constant f.5 $0e constant f.6 $0f constant f.7 cpuHERE constant flags2 1 cpuALLOT $10 constant weighing cpuHERE constant mode 1 cpuALLOT cpuHERE constant tempd 2 cpuALLOT \ decimal cpuHERE constant vbusr 2 cpuALLOT \ voltage ADC cpuHERE constant vbusd 2 cpuALLOT \ decimal cpuHERE constant talk0 1 cpuALLOT cpuHERE constant talk1 1 cpuALLOT cpuHERE constant talker 1 cpuALLOT cpuHERE constant ptalker 1 cpuALLOT cpuHERE constant slashx 1 cpuALLOT cpuHERE constant story 16 cpuALLOT cpuHERE constant guard 2 cpuALLOT [ cpuHERE constant red 1 cpuALLOT cpuHERE constant grn 1 cpuALLOT cpuHERE constant blu 1 cpuALLOT ] 3 constant x \ graphics x coordinate 4 constant y \ graphics y coordinate cpuHERE constant i2cb 64 cpuALLOT cr .( RAM used ) cpuHERE . .( bytes ) : swapctx [ 0 push 1 push t push psw push dph push dpl push ] SP (#@) [ other xch ] SP (#!) [ dpl pop dph pop psw pop t pop 1 pop 0 pop ] ; : 0# dup [ clra ] ; : key begin TI0 clr RI0 0=while. swapctx repeat RI0 clr SBUF0 #@ ; \ XXX compare with spidriver : emit SBUF0 (#!) begin swapctx RI0 clr TI0 until. TI0 clr [ charc dec ] : _drop drop ; :m drop; _drop ; m; : umax clrc $96 , $26 , \ C set if u>t if' drop; then nip ; : umin clrc $96 , $26 , \ C set if u>t 0=if' drop; then nip ; : depth S #@ invert ; 0 [if] include debug.fs [then] : 1ms 1 # : ms slowc (#!) begin slowc (#@) 0=until drop; : 5µs 5 # : µs 1 #for nop nop nop nop nop nop nop nop 1 #next ; \ ---------------------------------------- DECIMAL 5 constant d.l \ decimal accumulator 6 constant d.h : decimal ( u. -- d. ) \ d is the BCD of u 0 # d.l #! 0 # d.h #! 16 # 7 #for swap 2*' swap 2*' d.l #@ [ d.l addc da ] d.l #! d.h #@ [ d.h addc da ] d.h #! 7 #next 2drop d.l #@ d.h #@ ; : 10trunc swap $f0 # and swap ; : 5trunc swap dup $f # and 5 # crc) CRC0IN (#!) m; : hdigit dup : (hdigit) [swap] : digit $f # and -10 # + -if -39 # + then 97 # + emit ; : dd hdigit digit ; : >i2c MASTER 0=if. drop; then (>crc) SMB0DAT #! : i2c [ SI clr ] : (i2c) [ timeout clr ] : i2c-wait $01 # EIE1 ior! \ ESMB0 t3+ begin swapctx SI until. t3- $01 ~# EIE1 and! \ ESMB0 ; : i2c-start [ STA set ] i2c [ STA clr ] ; : i2c-stop [ STO set SI clr ] ; : i2c> MASTER 0=if. $ff # ; then i2c SMB0DAT #@ (>crc) ; : i2c-leave SMB0CF #@ 7 .t 0=if. drop; then \ already turned off 5 .t if. i2c-stop 10 # µs then \i2chw $04 ~# XBR0 and! drop; : setport ( u ) \ SCL SCL_DIR SDA SDA_DIR P0MDOUT ftemp mov 2/' f.2 movcb ftemp P0MDOUT mov 2/' P0.2 movcb P1MDOUT ftemp mov 2/' f.4 movcb ftemp P1MDOUT mov 2/' P1.4 movcb ; : i2c-restore %1010 # setport drop /i2chw $04 # XBR0 ior! ; : i2c-reset i2c-leave [ SDA set SCL clr ] 10 # 2 #for [ SCL set ] 5µs [ SCL clr ] 5µs 2 #next \ a STOP signal (SDA from low to high while CLK is high) [ SDA clr ] 5µs [ SCL set ] 2 # µs [ SDA set ] 2 # µs i2c-restore STO clr ; : bitbang i2c-leave begin key '@' # =if drop; then setport 2/' if' 0# P1.4 movbc 2*' P0.2 movbc 2*' emit then drop again : doconv startconv begin AD0INT until. AD0INT clr ; : measure ( - ) \ doconv ADC0H #@ emit ; : startweigh ( u ) weighing set i2c-leave [ SCL set SDA set ] %00000100 ~# P0MDIN and! %00010000 ~# P1MDIN and! : pulldir ( u ) [ \ Set pullup/down direction (1=up, 0=down) 2/' P0.0 movcb 2/' P0.1 movcb 2/' P0.3 movcb 2/' P1.5 movcb 2/' P1.6 movcb 2/' P2.0 movcb ] drop; : weigh 0# [ weighing movbc ] 2*' \ 1=pending, 0=ready dup emit 0=if 0# µs 3.3v %0010 # ADC0MX #! measure %1100 # ADC0MX #! measure %00000100 # P0MDIN ior! %00010000 # P1MDIN ior! dup /converter convs #! %111111 # pulldir i2c-restore then drop; \ ---------------------------------------- timer service : timer2 [ psw push t push ] [ slowc dec setc clra 0 clock dup addc da (#!) clra 1 clock dup addc da (#!) clra 2 clock dup addc da (#!) clra 3 clock dup addc da (#!) clra 4 clock dup addc da (#!) clra 5 clock dup addc da (#!) ] [ t pop psw pop ] ; : timer3a \i2chw timeout set SI set /i2chw [ reti ] \ ---------------------------------------- CRC16 :m /crc %1100 # CRC0CN0 #! m; :m crc16 CRC0DAT #@ CRC0DAT #@ m; \ ---------------------------------------- pullups \ P0.0 SDA 2K2 \ P0.1 SDA 4K3 \ P0.2 SDA \ P0.3 SDA 4K7 \ P1.4 SCL \ P1.5 SCL 2K2 \ P1.6 SCL 4K3 \ P2.0 SCL 4K7 : SDA_2k2 %00000001 # P0MDOUT ior! ; : SDA_4k3 %00000010 # P0MDOUT ior! ; : SDA_4k7 %00001000 # P0MDOUT ior! ; : SCL_2k2 %00100000 # P1MDOUT ior! ; : SCL_4k3 %01000000 # P1MDOUT ior! ; : SCL_4k7 %00000001 # P2MDOUT ior! ; \ 5 4 3 2 1 0 \ SCL_4k7 SCL_4k3 SCL_2k2 SDA_4k7 SDA_4k3 SDA_2k2 : pull@ ( - u ) 0# [ P2MDOUT ftemp mov f.0 movbc 2*' P1MDOUT ftemp mov f.6 movbc 2*' f.5 movbc 2*' P0MDOUT ftemp mov f.3 movbc 2*' f.1 movbc 2*' f.0 movbc 2*' ] ; : pull! ( u ) [ P0MDOUT ftemp mov 2/' f.0 movcb 2/' f.1 movcb 2/' f.3 movcb ftemp P0MDOUT mov P1MDOUT ftemp mov 2/' f.5 movcb 2/' f.6 movcb ftemp P1MDOUT mov P2MDOUT ftemp mov 2/' f.0 movcb ftemp P2MDOUT mov ] drop; : release %00001011 ~# P0MDOUT and! %01100000 ~# P1MDOUT and! %00000001 ~# P2MDOUT and! ; : weak release %00001000 # P0MDOUT ior! %00000001 # P2MDOUT ior! ; here constant "devname ," i2cdriver1" : heatmap ( u - ) \ heatmap address in x $80 # + dpl #! ; : ishot ( u ) heatmap 72 # !x ; : snap [ log dpl mov ] story # a! dup 16 # 7 #for [ dpl dec ] $7f # dpl and! (@x) (!+) 7 #next drop; : type @p+ 2 #for @p+ emit 2 #next ; : hdigit dup : (hdigit) [swap] : digit $f # and -10 # + -if -39 # + then 97 # + emit ; : dd hdigit digit ; : dh. dd : h. dd : space 32 # emit ; : point '.' # emit ; : d.d hdigit point digit ; : .' \ print carry [ '0' 2/ ] # 2*' : emit_ emit space ; : i2c-speed TH0 #@ I2C_400 # =if 4 (#) ; then 1 (#) ; : modechar 'I' # SMB0CF ftemp mov f.7 if. ; then 'B' (#) ; : bracket 79 # charc #! '[' # emit ; : info bracket "devname ##p! type space "serial ##p! type space 5 clock #@ dd 4 clock #@ dd 3 clock #@ dd 2 clock #@ dd 1 clock #@ (hdigit) space vbusd #2@ d.d dd space currd #2@ digit dd space tempd #2@ digit d.d space modechar emit_ [ SDA movbc ] .' [ SCL movbc ] .' i2c-speed digit $00 # dd space pull@ dd space crc16 dd dd : pad charc #@ begin space 1- 0=until drop ']' # emit ; : introspect bracket $93 # h. 0 #@ h. SP #@ h. SMB0CF #@ h. SMB0CN #@ h. TMR2L #2@ dh. TMR3L #2@ dh. IE #@ h. EIE1 #@ h. P0 #@ h. P0MDIN #@ h. P0MDOUT #@ h. P1 #@ h. P1MDIN #@ h. P1MDOUT #@ h. P2 #@ h. P2MDOUT #@ h. convs #@ h. pad ; \ Commands are: \ e echo next byte \ s select \ u unselect \ 80-bf read 1-64 bytes \ c0-ff write 1-64 bytes : count ( u -- u) 63 # and 1+ ; CLOSEUP [IF] :m acmd \ Copy ACK into T.7 for a command byte [ 7 .t set ] m; [ELSE] :m acmd \ Copy ACK into T.7 for a command byte [ ACK movbc 7 .t movcb ] m; [THEN] : b>log ( arg - arg ) 3 # acmd over : >log ( cmd arg ) [ dirty set ] [ log dpl mov ] !x+ !x+ $7f # dpl and! [ dpl log mov ] ; : alert ( u ) [ timeout set ] drop 4 # 0 # >log ; : rdN ( n -- ) [ ACK set ] 2 #for [ $b8 2 + ] , [ 1 cond ] \ Clear ACK on final byte when R2 is 1 [ ACK clr ] then i2c> (>crc) b>log emit 2 #next ; : rdNA ( n -- ) \ don't NACK final byte [ ACK set ] 2 #for i2c> b>log emit 2 #next ; : report [ '0' 2/ 2/ 2/ ] # [ ARBLOST movbc ] 2*' [ timeout movbc ] 2*' [ ACK movbc ] 2*' emit ; : flame ( u - u ) dup clrc 2/' ishot ; : do-start key : log-start ( u ) SDA 0=if. alert ; then i2c-start dup >i2c timeout if. alert ; then ACK if. flame then 2 # acmd swap >log ; : log-stop 1 # 0# >log i2c-stop ; : i2c-regrd \ expect (dev, reg, len) key 2* key key push ( dev reg R: len ) over log-start \ S/W b>log >i2c \ reg 1+ log-start \ S/R pop rdN log-stop ; : dmode 'D' # : newmode mode #! modechange. set ; here constant WIP : device-scan 8 # 112 # 2 #for i2c-start dup 2* >i2c ACK if. dup ishot then report i2c-stop 1+ 2 #next drop ; : service key -if 6 .t if. count dup i2cb # a! 2 #for key b>log !+ 2 #next i2cb # a! 2 #for @+ >i2c 2 #next report ; then count rdN ; then '?' # =if info then '1' # =if 100Khz then '4' # =if 400Khz then 'a' # =if key rdNA then 'b' # =if bitbang then 'c' # =if 'C' # newmode then 'd' # =if device-scan then 'e' # =if key emit then 'f' # =if fade. set 'X' # emit then '_' # =if $10 # RSTSRC #! then 'i' # =if i2c-restore then 'm' # =if 'M' # newmode then 'p' # =if log-stop then 'r' # =if i2c-regrd then 's' # =if do-start report then 'u' # =if key pull! then 'v' # =if key startweigh then 'w' # =if weigh then 'x' # =if i2c-reset [ '0' 2/ 2/ ] # [ SDA movbc ] 2*' [ SCL movbc ] 2*' emit then 'J' # =if introspect then drop ; : thread2 0 # 2 #for 0# !x+ 2 #next \ '@' # emit begin service again ; here constant _cap [ : fwd 0 constant ; ] include capture.fs _cap org [ : fwd bl word find 0= throw execute 0= throw ; ] include capture.fs 0 constant Y_V 29 constant X_V 80 constant X_MA include st7735.fs : hdigit dup [swap] : digit $f # and '0' # + ch ; : dd hdigit digit ; : d3 ( d. ) \ 3-digit space padded if digit dd ; then \ ### drop blch 10 # body @ ] ##p! [ dpl push dph push 0 push ] [ STACKS 8 + ] # other #! $100 SP! $c0 RP! %11001011 # P0SKIP #! \ TX,RX,SDA %00010000 # P0MDOUT #! \ %00111111 # P0MDIN #! \ analog P0.6 P0.7 %11101111 # P1SKIP #! \ SCL %00001111 # P1MDOUT #! /uart /adc /crc [ ticks/ms negate ] # TMR2RLL #! [ ticks/ms negate 8 rshift ] # TMR2RLH #! dmode [ ET2 set ] \ Timer 2 interrupt enable [ TR2 set ] \ Timer 2 enable [ EA set ] t3i+ release weak \ SDA_2k2 \ SDA_4k3 \ SDA_4k7 \ SCL_2k2 \ SCL_4k3 \ SCL_4k7 /i2c 100Khz [ dirty set ] swapctx /st7735 fixed 25 # slowc #! /converter begin conversions dirty if. snap [ dirty clr ] waves then AD0INT if. AD0INT clr convs #@ converter convs #! then modechange. if. [ modechange. clr ] drawmode mode #@ 'C' # =if capture dmode then 'M' # =if /monitor then drop then mode #@ 'M' # =if TMR3CN #@ -if $7f # TMR3CN and! cool then drop RI0 if. RI0 clr \monitor dmode then then drop slowc #@ \ 4 Hz 0=if results then CLOSEUP [IF] fade. if. cool [ fade. clr ] then [ELSE] $1f # and 0=if \ 32 Hz cool then [THEN] drop again here \ Reset $000 org go ; \ UART interrupt $023 org swapctx [ reti ] \ Timer 2 overflow $02b org [ ] timer2 [ TF2H clr reti ] \ I2C $03b org swapctx [ reti ] \ Port mismatch $043 org mismatch \ Timer 3 overflow $073 org FL1 if. timer3 then timer3a ; org ================================================ FILE: firmware/st7735.fs ================================================ $00 constant NOP $2B constant RASET $C2 constant PWCTR3 $01 constant SWRESET $2C constant RAMWR $C3 constant PWCTR4 $04 constant RDDID $2E constant RAMRD $C4 constant PWCTR5 $09 constant RDDST $30 constant PTLAR $C5 constant VMCTR1 $10 constant SLPIN $36 constant MADCTL $DA constant RDID1 $11 constant SLPOUT $3A constant COLMOD $DB constant RDID2 $12 constant PTLON $B1 constant FRMCTR1 $DC constant RDID3 $13 constant NORON $B2 constant FRMCTR2 $DD constant RDID4 $20 constant INVOFF $B3 constant FRMCTR3 $E0 constant GMCTRP1 $21 constant INVON $B4 constant INVCTR $E1 constant GMCTRN1 $28 constant DISPOFF $B6 constant DISSET5 $FC constant PWCTR6 $29 constant DISPON $C0 constant PWCTR1 $2A constant CASET $C1 constant PWCTR2 $80 constant DELAY here constant init-table SWRESET , DELAY , \ Software reset, 0 args, w/delay 60 , SLPOUT , DELAY , \ Out of sleep mode, 0 args, w/delay 60 , FRMCTR1 , 3 , \ Frame rate ctrl - normal mode, 3 args: 0x01 , 0x2C , 0x2D , \ Rate = fosc/(1x2+40) * (LINE+2C+2D) FRMCTR2 , 3 , \ Frame rate control - idle mode, 3 args: 0x01 , 0x2C , 0x2D , \ Rate = fosc/(1x2+40) * (LINE+2C+2D) FRMCTR3 , 6 , \ Frame rate ctrl - partial mode, 6 args: 0x01 , 0x2C , 0x2D , \ Dot inversion mode 0x01 , 0x2C , 0x2D , \ Line inversion mode PWCTR1 , 3 , \ Power control, 3 args: 0xA2 , 0x02 , \ -4.6V 0x84 , \ AUTO mode PWCTR2 , 1 , \ Power control, 1 arg: 0xC5 , \ VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD PWCTR3 , 2 , \ Power control, 2 args: 0x0A , \ Opamp current small 0x00 , \ Boost frequency PWCTR4 , 2 , \ Power control, 2 args: 0x8A , \ BCLK/2, Opamp current small & Medium low 0x2A , PWCTR5 , 2 , \ Power control, 2 args: 0x8A , 0xEE , VMCTR1 , 1 , \ Power control, 1 arg: 0x0E , MADCTL , 1 , \ Memory access control (directions), 1 arg: 0xC8 , \ row addr/col addr, bottom to top refresh COLMOD , 1 , \ set color mode, 1 arg: 0x03 , \ 12-bit color GMCTRP1 , 16 , \ Gamma + polarity Correction Characterstics 0x02 , 0x1c , 0x07 , 0x12 , 0x37 , 0x32 , 0x29 , 0x2d , 0x29 , 0x25 , 0x2B , 0x39 , 0x00 , 0x01 , 0x03 , 0x10 , GMCTRN1 , 16 , \ Gamma - polarity Correction Characterstics 0x03 , 0x1d , 0x07 , 0x06 , 0x2E , 0x2C , 0x29 , 0x2D , 0x2E , 0x2E , 0x37 , 0x3F , 0x00 , 0x00 , 0x02 , 0x10 , NORON , 0 , \ Normal display on 0 , :m clk [ 2 .p1 set 2 .p1 clr ] m; :m 1bit 2*' 1 .p1 movcb clk m; :m /C/ [ 0 .p1 clr ] m; :m /D/ [ 0 .p1 set ] m; : (>st) 1bit 1bit 1bit 1bit : _4 1bit 1bit 1bit 1bit 2*' ; : (4>st) 2*' 2*' 2*' 2*' _4 ; : 4>st (4>st) drop ; : write-cmd ( b ) /C/ : 1>st ( b ) 1bit 1bit 1bit 1bit 1bit 1bit 1bit 1bit drop ; : write-data ( b ) /D/ 1>st ; : data16 ( b ) 0# write-data write-data ; : args begin 0=if drop; then @p+ write-data 1- again : coldregs init-table ##p! begin @p+ 0=if drop; then write-cmd @p+ dup $7f # and args -if @p+ ms then drop again here [ $1000 > throw ] $1000 org : dim ( x w ) over data16 + 1- data16 ; : rect ( x y w h ) twist ( x w y h ) RASET # write-cmd dim CASET # write-cmd dim : writing RAMWR # write-cmd /D/ ; : full blu #@ (4>st) grn (#@) (4>st) red (#@) 4>st ; :m |4>st 1bit 1bit 1bit 1bit m; : half 10 # : gray 0=if drop : dark 1 .p1 clr clk clk clk clk clk clk clk clk clk clk clk clk ; then 5 (#!) [ blu b mov mul ] $f # + |4>st 5 (#@) [ grn b mov mul ] $f # + |4>st 5 (#@) [ red b mov mul ] $f # + |4>st drop ; : ndark 7 #for dark 7 #next ; : cls ( ) 0# 0# 128 # 160 # rect 160 # 6 #for 128 # ndark 6 #next ; : /st7735 [ 3 .p1 clr ] 1 # ms [ 3 .p1 set ] coldregs cls : white $f # : setgray red (#!) grn (#!) blu #! ; : black 0# setgray ; $1fff constant TOPMEM 947 here include fontsize.fs [ TOPMEM FONTDATA_SIZE - ] org include font.fs here TOPMEM <> throw org 947 <> throw :m 4.4r ( - l h ) dup clra dup $93 , $a3 , \ |@p+ xchd [swap] m; : 4.4 ( - h l ) 4.4r swap ; : skip 4.4 * 1+ clrc 2/' : +p [ dpl add ] dpl (#!) [ clra dph addc ] dph (#!) drop; : seek ( c - ) \ p points to the data for character c font ##p! begin dup @p+ xor 0=if 2drop ; then drop skip again : xy! y #! x #! ; : xy@ x #@ y #@ ; : adv x #+! ; \ advance cursor : preloop ( l h - i j ) swap if 1u+ then ; \ Fill rect with current color : wash ( x y w h ) 2dup um* d1+ d2/ preloop 7 #! 6 #! rect begin begin full full 7 #next 6 #next ; : ch ( c - ) p>r seek xy@ 4.4 ( w h ) over adv 2dup * push ( w h r: w*h ) rect pop 1+ 2/ 7 #for 4.4r gray gray 7 #next r>p ; : blch black xy@ 8 # 9 # wash 8 # adv white ; : str @p+ 6 #for @p+ ch 6 #next ; : setcolor 4.4 grn #! red #! @p+ blu #! ; : hex1 ( h - ) x #@ 3 # + $7f # xor 4 # RASET # write-cmd dim RAMWR # write-cmd /D/ micro ##p! $f # and 10 # b #! [ mul ] +p 10 # 7 #for 4.4r gray gray 7 #next 5 # x #+! ; : drawhex ( hh - ) y #@ 5 # CASET # write-cmd dim dup [swap] hex1 hex1 ; :m gap [ y inc ] m; : clip y #@ : (clip) -if $7f # and negate + ; then drop; : preblank ( w ) dup y #@ + (clip) dup push x #@ -4 # + y #@ 16 # pop rect 6 #for 16 # ndark 6 #next ; : bitmap 0 # : +bitmap ( o ) x #@ + y #@ -if 2drop ; then 4.4 ( w h ) : (bitmap) ( x y w h ) dup y #+! clip 2dup * push ( w h r: w*h ) rect pop 1+ clrc 2/' 7 #for 4.4r gray gray 7 #next ; : (hex2) micro ##p! $f # and 10 # * +p y #@ -if drop; then drop x #@ 3 # + y #@ 5 # 4 # (bitmap) ; : hex2 ( u - ) dup (hex2) gap [swap] (hex2) ; : acknak 0=if' $c # red #! $2 # grn #! $2 # blu #! ; then $2 # red #! $c # grn #! $2 # blu #! ; : d-byte-ack acknak 18 # preblank gap dot ##p! 7 # +bitmap gap white hex2 gap gap gap ; : barpoint ( u - ) \ update the slash bar bounds -if drop; then dup talk0 #@ umin talk0 #! talk1 #@ umax talk1 #! ; : slashcolor 8 # setgray ; here constant DRAW-SEGMENT \ This block must all be in the same 2K segment : startwave 128 # 7 #! 0 # 8 # 128 # rect story # a! [ SP x mov x dec x dec 0 y mov ] ; : column $df cond : bail [ x SP mov y 0 mov ] then ; : hi full dark dark dark dark dark dark dark column ; : lo dark dark dark dark dark dark dark full column ; : change full full full full full full full full column ; : undef half half half half half half half half column ; : d-stop drop a+ 0 # red #! 7 # grn #! 7 # blu #! symbol-p ##p! : (d-stop) 12 # preblank bitmap ; :m y; \ return if y>127 $bc , 128 , 0 , \ CJNE R4,#128,+0 0=if' ; then m; : d-direction arrow ##p! if' larrow ##p! then $f # red #! $e # grn #! $2 # blu #! -5 # y #+! bitmap ; : slashv ( u - ) \ draw the bottom slash segment $08 # madctl MADCTL # write-cmd write-data ; : ltr %11001000 # >madctl ; : drawmode black 0# 0# 2dup 10 # 9 # wash white xy! mode #@ ch ; : fixed rtl 3 # setgray $08 # 112 # 6 #for dup d-addr 1+ 6 #next ltr drawmode tplan ##p! begin @p+ 0=if drop; then @p+ xy! setcolor str again : d-slash talked. if. ptalked. if. ptalker #@ talker @=if drop; then unslash then talker #@ slash ; then ptalker #@ unslash ; : cool1 ( addr - ) \ talker @=if talked. if. drop; then then dup heatmap @x if ( addr h ) 1- (!x) ingrad d-addr ; then 2drop ; : cool rtl $08 # 112 # 6 #for dup cool1 1+ 6 #next drop ltr ; \ talked. is true when talker is valid \ ptalked. and ptalker hold previous values \ slashx is set to the X of the slash line : waves \ pinkwash rtl 122 # 0 # xy! $ff # talk0 #! $00 # talk1 #! talked. clr story # a! l-dispatch d-sda d-scl ltr d-slash d-slashbar talker #@ ptalker #! [ talked. movbc ptalked. movcb ] DISPON # write-cmd ; ================================================ FILE: hardware/i2cdriver.brd ================================================ <b>Resistors, Capacitors, Inductors</b><p> Based on the previous libraries: <ul> <li>r.lbr <li>cap.lbr <li>cap-fe.lbr <li>captant.lbr <li>polcap.lbr <li>ipc-smd.lbr </ul> All SMD packages are defined according to the IPC specifications and CECC<p> <author>Created by librarian@cadsoft.de</author><p> <p> for Electrolyt Capacitors see also :<p> www.bccomponents.com <p> www.panasonic.com<p> www.kemet.com<p> http://www.secc.co.jp/pdf/os_e/2004/e_os_all.pdf <b>(SANYO)</b> <p> for trimmer refence see : <u>www.electrospec-inc.com/cross_references/trimpotcrossref.asp</u><p> <table border=0 cellspacing=0 cellpadding=0 width="100%" cellpaddding=0> <tr valign="top"> <! <td width="10">&nbsp;</td> <td width="90%"> <b><font color="#0000FF" size="4">TRIM-POT CROSS REFERENCE</font></b> <P> <TABLE BORDER=0 CELLSPACING=1 CELLPADDING=2> <TR> <TD COLSPAN=8> <FONT SIZE=3 FACE=ARIAL><B>RECTANGULAR MULTI-TURN</B></FONT> </TD> </TR> <TR> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">BOURNS</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">BI&nbsp;TECH</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">DALE-VISHAY</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">PHILIPS/MEPCO</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">MURATA</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">PANASONIC</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">SPECTROL</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">MILSPEC</FONT> </B> </TD><TD>&nbsp;</TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3 > 3005P<BR> 3006P<BR> 3006W<BR> 3006Y<BR> 3009P<BR> 3009W<BR> 3009Y<BR> 3057J<BR> 3057L<BR> 3057P<BR> 3057Y<BR> 3059J<BR> 3059L<BR> 3059P<BR> 3059Y<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 89P<BR> 89W<BR> 89X<BR> 89PH<BR> 76P<BR> 89XH<BR> 78SLT<BR> 78L&nbsp;ALT<BR> 56P&nbsp;ALT<BR> 78P&nbsp;ALT<BR> T8S<BR> 78L<BR> 56P<BR> 78P<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> T18/784<BR> 783<BR> 781<BR> -<BR> -<BR> -<BR> 2199<BR> 1697/1897<BR> 1680/1880<BR> 2187<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 8035EKP/CT20/RJ-20P<BR> -<BR> RJ-20X<BR> -<BR> -<BR> -<BR> 1211L<BR> 8012EKQ&nbsp;ALT<BR> 8012EKR&nbsp;ALT<BR> 1211P<BR> 8012EKJ<BR> 8012EKL<BR> 8012EKQ<BR> 8012EKR<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 2101P<BR> 2101W<BR> 2101Y<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 2102L<BR> 2102S<BR> 2102Y<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> EVMCOG<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 43P<BR> 43W<BR> 43Y<BR> -<BR> -<BR> -<BR> -<BR> 40L<BR> 40P<BR> 40Y<BR> 70Y-T602<BR> 70L<BR> 70P<BR> 70Y<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> RT/RTR12<BR> RT/RTR12<BR> RT/RTR12<BR> -<BR> RJ/RJR12<BR> RJ/RJR12<BR> RJ/RJR12<BR></FONT> </TD> </TR> <TR> <TD COLSPAN=8>&nbsp; </TD> </TR> <TR> <TD COLSPAN=8> <FONT SIZE=4 FACE=ARIAL><B>SQUARE MULTI-TURN</B></FONT> </TD> </TR> <TR> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BOURN</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MURATA</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>SPECTROL</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MILSPEC</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3250L<BR> 3250P<BR> 3250W<BR> 3250X<BR> 3252P<BR> 3252W<BR> 3252X<BR> 3260P<BR> 3260W<BR> 3260X<BR> 3262P<BR> 3262W<BR> 3262X<BR> 3266P<BR> 3266W<BR> 3266X<BR> 3290H<BR> 3290P<BR> 3290W<BR> 3292P<BR> 3292W<BR> 3292X<BR> 3296P<BR> 3296W<BR> 3296X<BR> 3296Y<BR> 3296Z<BR> 3299P<BR> 3299W<BR> 3299X<BR> 3299Y<BR> 3299Z<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 66P&nbsp;ALT<BR> 66W&nbsp;ALT<BR> 66X&nbsp;ALT<BR> 66P&nbsp;ALT<BR> 66W&nbsp;ALT<BR> 66X&nbsp;ALT<BR> -<BR> 64W&nbsp;ALT<BR> -<BR> 64P&nbsp;ALT<BR> 64W&nbsp;ALT<BR> 64X&nbsp;ALT<BR> 64P<BR> 64W<BR> 64X<BR> 66X&nbsp;ALT<BR> 66P&nbsp;ALT<BR> 66W&nbsp;ALT<BR> 66P<BR> 66W<BR> 66X<BR> 67P<BR> 67W<BR> 67X<BR> 67Y<BR> 67Z<BR> 68P<BR> 68W<BR> 68X<BR> 67Y&nbsp;ALT<BR> 67Z&nbsp;ALT<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 5050<BR> 5091<BR> 5080<BR> 5087<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> T63YB<BR> T63XB<BR> -<BR> -<BR> -<BR> 5887<BR> 5891<BR> 5880<BR> -<BR> -<BR> -<BR> T93Z<BR> T93YA<BR> T93XA<BR> T93YB<BR> T93XB<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 8026EKP<BR> 8026EKW<BR> 8026EKM<BR> 8026EKP<BR> 8026EKB<BR> 8026EKM<BR> 1309X<BR> 1309P<BR> 1309W<BR> 8024EKP<BR> 8024EKW<BR> 8024EKN<BR> RJ-9P/CT9P<BR> RJ-9W<BR> RJ-9X<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 3103P<BR> 3103Y<BR> 3103Z<BR> 3103P<BR> 3103Y<BR> 3103Z<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 3105P/3106P<BR> 3105W/3106W<BR> 3105X/3106X<BR> 3105Y/3106Y<BR> 3105Z/3105Z<BR> 3102P<BR> 3102W<BR> 3102X<BR> 3102Y<BR> 3102Z<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> EVMCBG<BR> EVMCCG<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 55-1-X<BR> 55-4-X<BR> 55-3-X<BR> 55-2-X<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 50-2-X<BR> 50-4-X<BR> 50-3-X<BR> -<BR> -<BR> -<BR> 64P<BR> 64W<BR> 64X<BR> 64Y<BR> 64Z<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> RT/RTR22<BR> RT/RTR22<BR> RT/RTR22<BR> RT/RTR22<BR> RJ/RJR22<BR> RJ/RJR22<BR> RJ/RJR22<BR> RT/RTR26<BR> RT/RTR26<BR> RT/RTR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RT/RTR24<BR> RT/RTR24<BR> RT/RTR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> </TR> <TR> <TD COLSPAN=8>&nbsp; </TD> </TR> <TR> <TD COLSPAN=8> <FONT SIZE=4 FACE=ARIAL><B>SINGLE TURN</B></FONT> </TD> </TR> <TR> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BOURN</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MURATA</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>SPECTROL</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MILSPEC</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3323P<BR> 3323S<BR> 3323W<BR> 3329H<BR> 3329P<BR> 3329W<BR> 3339H<BR> 3339P<BR> 3339W<BR> 3352E<BR> 3352H<BR> 3352K<BR> 3352P<BR> 3352T<BR> 3352V<BR> 3352W<BR> 3362H<BR> 3362M<BR> 3362P<BR> 3362R<BR> 3362S<BR> 3362U<BR> 3362W<BR> 3362X<BR> 3386B<BR> 3386C<BR> 3386F<BR> 3386H<BR> 3386K<BR> 3386M<BR> 3386P<BR> 3386S<BR> 3386W<BR> 3386X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 25P<BR> 25S<BR> 25RX<BR> 82P<BR> 82M<BR> 82PA<BR> -<BR> -<BR> -<BR> 91E<BR> 91X<BR> 91T<BR> 91B<BR> 91A<BR> 91V<BR> 91W<BR> 25W<BR> 25V<BR> 25P<BR> -<BR> 25S<BR> 25U<BR> 25RX<BR> 25X<BR> 72XW<BR> 72XL<BR> 72PM<BR> 72RX<BR> -<BR> 72PX<BR> 72P<BR> 72RXW<BR> 72RXL<BR> 72X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> T7YB<BR> T7YA<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> TXD<BR> TYA<BR> TYP<BR> -<BR> TYD<BR> TX<BR> -<BR> 150SX<BR> 100SX<BR> 102T<BR> 101S<BR> 190T<BR> 150TX<BR> 101<BR> -<BR> -<BR> 101SX<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> ET6P<BR> ET6S<BR> ET6X<BR> RJ-6W/8014EMW<BR> RJ-6P/8014EMP<BR> RJ-6X/8014EMX<BR> TM7W<BR> TM7P<BR> TM7X<BR> -<BR> 8017SMS<BR> -<BR> 8017SMB<BR> 8017SMA<BR> -<BR> -<BR> CT-6W<BR> CT-6H<BR> CT-6P<BR> CT-6R<BR> -<BR> CT-6V<BR> CT-6X<BR> -<BR> -<BR> 8038EKV<BR> -<BR> 8038EKX<BR> -<BR> -<BR> 8038EKP<BR> 8038EKZ<BR> 8038EKW<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> 3321H<BR> 3321P<BR> 3321N<BR> 1102H<BR> 1102P<BR> 1102T<BR> RVA0911V304A<BR> -<BR> RVA0911H413A<BR> RVG0707V100A<BR> RVA0607V(H)306A<BR> RVA1214H213A<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 3104B<BR> 3104C<BR> 3104F<BR> 3104H<BR> -<BR> 3104M<BR> 3104P<BR> 3104S<BR> 3104W<BR> 3104X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> EVMQ0G<BR> EVMQIG<BR> EVMQ3G<BR> EVMS0G<BR> EVMQ0G<BR> EVMG0G<BR> -<BR> -<BR> -<BR> EVMK4GA00B<BR> EVM30GA00B<BR> EVMK0GA00B<BR> EVM38GA00B<BR> EVMB6<BR> EVLQ0<BR> -<BR> EVMMSG<BR> EVMMBG<BR> EVMMAG<BR> -<BR> -<BR> EVMMCS<BR> -<BR> -<BR> -<BR> -<BR> -<BR> EVMM1<BR> -<BR> -<BR> EVMM0<BR> -<BR> -<BR> EVMM3<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> 62-3-1<BR> 62-1-2<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 67R<BR> -<BR> 67P<BR> -<BR> -<BR> -<BR> -<BR> 67X<BR> 63V<BR> 63S<BR> 63M<BR> -<BR> -<BR> 63H<BR> 63P<BR> -<BR> -<BR> 63X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> RJ/RJR50<BR> RJ/RJR50<BR> RJ/RJR50<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> </TR> </TABLE> <P>&nbsp;<P> <TABLE BORDER=0 CELLSPACING=1 CELLPADDING=3> <TR> <TD COLSPAN=7> <FONT color="#0000FF" SIZE=4 FACE=ARIAL><B>SMD TRIM-POT CROSS REFERENCE</B></FONT> <P> <FONT SIZE=4 FACE=ARIAL><B>MULTI-TURN</B></FONT> </TD> </TR> <TR> <TD> <FONT SIZE=3 FACE=ARIAL><B>BOURNS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>TOCOS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>AUX/KYOCERA</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3224G<BR> 3224J<BR> 3224W<BR> 3269P<BR> 3269W<BR> 3269X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 44G<BR> 44J<BR> 44W<BR> 84P<BR> 84W<BR> 84X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> ST63Z<BR> ST63Y<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> ST5P<BR> ST5W<BR> ST5X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> </TR> <TR> <TD COLSPAN=7>&nbsp; </TD> </TR> <TR> <TD COLSPAN=7> <FONT SIZE=4 FACE=ARIAL><B>SINGLE TURN</B></FONT> </TD> </TR> <TR> <TD> <FONT SIZE=3 FACE=ARIAL><B>BOURNS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>TOCOS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>AUX/KYOCERA</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3314G<BR> 3314J<BR> 3364A/B<BR> 3364C/D<BR> 3364W/X<BR> 3313G<BR> 3313J<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 23B<BR> 23A<BR> 21X<BR> 21W<BR> -<BR> 22B<BR> 22A<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> ST5YL/ST53YL<BR> ST5YJ/5T53YJ<BR> ST-23A<BR> ST-22B<BR> ST-22<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> ST-4B<BR> ST-4A<BR> -<BR> -<BR> -<BR> ST-3B<BR> ST-3A<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> EVM-6YS<BR> EVM-1E<BR> EVM-1G<BR> EVM-1D<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> G4B<BR> G4A<BR> TR04-3S1<BR> TRG04-2S1<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> DVR-43A<BR> CVR-42C<BR> CVR-42A/C<BR> -<BR> -<BR></FONT> </TD> </TR> </TABLE> <P> <FONT SIZE=4 FACE=ARIAL><B>ALT =&nbsp;ALTERNATE</B></FONT> <P> &nbsp; <P> </td> </tr> </table> <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> >NAME >VALUE PCB Edge >NAME >VALUE <b>Description:</b> Silicon Labs Busy Bee QFN20 Package.<br/> >NAME <b>Ceramic Chip Capacitor KEMET 0204 Reflow solder</b><p> Metric Code Size 1005 >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>FTDI (TM) CHIP</b> Future Technology Devices International Ltd.<p> http://www.ftdichip.com <b>QFN-16 4 x 4 mm</b><p> Source: <a href="http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT230X.pdf"> Data sheet </a> >NAME >VALUE <b>Burr-Brown Components</b><p> <author>Created by librarian@cadsoft.de</author> <b>Smal Outline Transistor</b> >NAME >VALUE >NAME >VALUE <b>Test Pins/Pads</b><p> Cream on SMD OFF.<br> new: Attribute TP_SIGNAL_NAME<br> <author>Created by librarian@cadsoft.de</author> <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>Pin Header Connectors</b><p> <author>Created by librarian@cadsoft.de</author> <b>PIN HEADER</b> >NAME >VALUE <b>EAGLE Design Rules</b> <p> Die Standard-Design-Rules sind so gewählt, dass sie für die meisten Anwendungen passen. Sollte ihre Platine besondere Anforderungen haben, treffen Sie die erforderlichen Einstellungen hier und speichern die Design Rules unter einem neuen Namen ab. <b>EAGLE Design Rules</b> <p> The default Design Rules have been set to cover a wide range of applications. Your particular design may have different requirements, so please make the necessary adjustments and save your customized design rules under a new name. <b>NOA-Labs EAGLE Design Rules</b> ================================================ FILE: hardware/i2cdriver.sch ================================================ JD-T1800 128x160 18-bit color 1.8" TFT >VALUE >VALUE <b>SUPPLY SYMBOL</b> <b>SUPPLY SYMBOL</b> <b>Resistors, Capacitors, Inductors</b><p> Based on the previous libraries: <ul> <li>r.lbr <li>cap.lbr <li>cap-fe.lbr <li>captant.lbr <li>polcap.lbr <li>ipc-smd.lbr </ul> All SMD packages are defined according to the IPC specifications and CECC<p> <author>Created by librarian@cadsoft.de</author><p> <p> for Electrolyt Capacitors see also :<p> www.bccomponents.com <p> www.panasonic.com<p> www.kemet.com<p> http://www.secc.co.jp/pdf/os_e/2004/e_os_all.pdf <b>(SANYO)</b> <p> for trimmer refence see : <u>www.electrospec-inc.com/cross_references/trimpotcrossref.asp</u><p> <table border=0 cellspacing=0 cellpadding=0 width="100%" cellpaddding=0> <tr valign="top"> <! <td width="10">&nbsp;</td> <td width="90%"> <b><font color="#0000FF" size="4">TRIM-POT CROSS REFERENCE</font></b> <P> <TABLE BORDER=0 CELLSPACING=1 CELLPADDING=2> <TR> <TD COLSPAN=8> <FONT SIZE=3 FACE=ARIAL><B>RECTANGULAR MULTI-TURN</B></FONT> </TD> </TR> <TR> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">BOURNS</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">BI&nbsp;TECH</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">DALE-VISHAY</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">PHILIPS/MEPCO</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">MURATA</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">PANASONIC</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">SPECTROL</FONT> </B> </TD> <TD ALIGN=CENTER> <B> <FONT SIZE=3 FACE=ARIAL color="#FF0000">MILSPEC</FONT> </B> </TD><TD>&nbsp;</TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3 > 3005P<BR> 3006P<BR> 3006W<BR> 3006Y<BR> 3009P<BR> 3009W<BR> 3009Y<BR> 3057J<BR> 3057L<BR> 3057P<BR> 3057Y<BR> 3059J<BR> 3059L<BR> 3059P<BR> 3059Y<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 89P<BR> 89W<BR> 89X<BR> 89PH<BR> 76P<BR> 89XH<BR> 78SLT<BR> 78L&nbsp;ALT<BR> 56P&nbsp;ALT<BR> 78P&nbsp;ALT<BR> T8S<BR> 78L<BR> 56P<BR> 78P<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> T18/784<BR> 783<BR> 781<BR> -<BR> -<BR> -<BR> 2199<BR> 1697/1897<BR> 1680/1880<BR> 2187<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 8035EKP/CT20/RJ-20P<BR> -<BR> RJ-20X<BR> -<BR> -<BR> -<BR> 1211L<BR> 8012EKQ&nbsp;ALT<BR> 8012EKR&nbsp;ALT<BR> 1211P<BR> 8012EKJ<BR> 8012EKL<BR> 8012EKQ<BR> 8012EKR<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 2101P<BR> 2101W<BR> 2101Y<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 2102L<BR> 2102S<BR> 2102Y<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> EVMCOG<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 43P<BR> 43W<BR> 43Y<BR> -<BR> -<BR> -<BR> -<BR> 40L<BR> 40P<BR> 40Y<BR> 70Y-T602<BR> 70L<BR> 70P<BR> 70Y<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> RT/RTR12<BR> RT/RTR12<BR> RT/RTR12<BR> -<BR> RJ/RJR12<BR> RJ/RJR12<BR> RJ/RJR12<BR></FONT> </TD> </TR> <TR> <TD COLSPAN=8>&nbsp; </TD> </TR> <TR> <TD COLSPAN=8> <FONT SIZE=4 FACE=ARIAL><B>SQUARE MULTI-TURN</B></FONT> </TD> </TR> <TR> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BOURN</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MURATA</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>SPECTROL</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MILSPEC</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3250L<BR> 3250P<BR> 3250W<BR> 3250X<BR> 3252P<BR> 3252W<BR> 3252X<BR> 3260P<BR> 3260W<BR> 3260X<BR> 3262P<BR> 3262W<BR> 3262X<BR> 3266P<BR> 3266W<BR> 3266X<BR> 3290H<BR> 3290P<BR> 3290W<BR> 3292P<BR> 3292W<BR> 3292X<BR> 3296P<BR> 3296W<BR> 3296X<BR> 3296Y<BR> 3296Z<BR> 3299P<BR> 3299W<BR> 3299X<BR> 3299Y<BR> 3299Z<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> 66P&nbsp;ALT<BR> 66W&nbsp;ALT<BR> 66X&nbsp;ALT<BR> 66P&nbsp;ALT<BR> 66W&nbsp;ALT<BR> 66X&nbsp;ALT<BR> -<BR> 64W&nbsp;ALT<BR> -<BR> 64P&nbsp;ALT<BR> 64W&nbsp;ALT<BR> 64X&nbsp;ALT<BR> 64P<BR> 64W<BR> 64X<BR> 66X&nbsp;ALT<BR> 66P&nbsp;ALT<BR> 66W&nbsp;ALT<BR> 66P<BR> 66W<BR> 66X<BR> 67P<BR> 67W<BR> 67X<BR> 67Y<BR> 67Z<BR> 68P<BR> 68W<BR> 68X<BR> 67Y&nbsp;ALT<BR> 67Z&nbsp;ALT<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 5050<BR> 5091<BR> 5080<BR> 5087<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> T63YB<BR> T63XB<BR> -<BR> -<BR> -<BR> 5887<BR> 5891<BR> 5880<BR> -<BR> -<BR> -<BR> T93Z<BR> T93YA<BR> T93XA<BR> T93YB<BR> T93XB<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 8026EKP<BR> 8026EKW<BR> 8026EKM<BR> 8026EKP<BR> 8026EKB<BR> 8026EKM<BR> 1309X<BR> 1309P<BR> 1309W<BR> 8024EKP<BR> 8024EKW<BR> 8024EKN<BR> RJ-9P/CT9P<BR> RJ-9W<BR> RJ-9X<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 3103P<BR> 3103Y<BR> 3103Z<BR> 3103P<BR> 3103Y<BR> 3103Z<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 3105P/3106P<BR> 3105W/3106W<BR> 3105X/3106X<BR> 3105Y/3106Y<BR> 3105Z/3105Z<BR> 3102P<BR> 3102W<BR> 3102X<BR> 3102Y<BR> 3102Z<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> EVMCBG<BR> EVMCCG<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 55-1-X<BR> 55-4-X<BR> 55-3-X<BR> 55-2-X<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 50-2-X<BR> 50-4-X<BR> 50-3-X<BR> -<BR> -<BR> -<BR> 64P<BR> 64W<BR> 64X<BR> 64Y<BR> 64Z<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> RT/RTR22<BR> RT/RTR22<BR> RT/RTR22<BR> RT/RTR22<BR> RJ/RJR22<BR> RJ/RJR22<BR> RJ/RJR22<BR> RT/RTR26<BR> RT/RTR26<BR> RT/RTR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RJ/RJR26<BR> RT/RTR24<BR> RT/RTR24<BR> RT/RTR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> RJ/RJR24<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> </TR> <TR> <TD COLSPAN=8>&nbsp; </TD> </TR> <TR> <TD COLSPAN=8> <FONT SIZE=4 FACE=ARIAL><B>SINGLE TURN</B></FONT> </TD> </TR> <TR> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BOURN</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MURATA</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>SPECTROL</B></FONT> </TD> <TD ALIGN=CENTER> <FONT SIZE=3 FACE=ARIAL><B>MILSPEC</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3323P<BR> 3323S<BR> 3323W<BR> 3329H<BR> 3329P<BR> 3329W<BR> 3339H<BR> 3339P<BR> 3339W<BR> 3352E<BR> 3352H<BR> 3352K<BR> 3352P<BR> 3352T<BR> 3352V<BR> 3352W<BR> 3362H<BR> 3362M<BR> 3362P<BR> 3362R<BR> 3362S<BR> 3362U<BR> 3362W<BR> 3362X<BR> 3386B<BR> 3386C<BR> 3386F<BR> 3386H<BR> 3386K<BR> 3386M<BR> 3386P<BR> 3386S<BR> 3386W<BR> 3386X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 25P<BR> 25S<BR> 25RX<BR> 82P<BR> 82M<BR> 82PA<BR> -<BR> -<BR> -<BR> 91E<BR> 91X<BR> 91T<BR> 91B<BR> 91A<BR> 91V<BR> 91W<BR> 25W<BR> 25V<BR> 25P<BR> -<BR> 25S<BR> 25U<BR> 25RX<BR> 25X<BR> 72XW<BR> 72XL<BR> 72PM<BR> 72RX<BR> -<BR> 72PX<BR> 72P<BR> 72RXW<BR> 72RXL<BR> 72X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> T7YB<BR> T7YA<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> TXD<BR> TYA<BR> TYP<BR> -<BR> TYD<BR> TX<BR> -<BR> 150SX<BR> 100SX<BR> 102T<BR> 101S<BR> 190T<BR> 150TX<BR> 101<BR> -<BR> -<BR> 101SX<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> ET6P<BR> ET6S<BR> ET6X<BR> RJ-6W/8014EMW<BR> RJ-6P/8014EMP<BR> RJ-6X/8014EMX<BR> TM7W<BR> TM7P<BR> TM7X<BR> -<BR> 8017SMS<BR> -<BR> 8017SMB<BR> 8017SMA<BR> -<BR> -<BR> CT-6W<BR> CT-6H<BR> CT-6P<BR> CT-6R<BR> -<BR> CT-6V<BR> CT-6X<BR> -<BR> -<BR> 8038EKV<BR> -<BR> 8038EKX<BR> -<BR> -<BR> 8038EKP<BR> 8038EKZ<BR> 8038EKW<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> 3321H<BR> 3321P<BR> 3321N<BR> 1102H<BR> 1102P<BR> 1102T<BR> RVA0911V304A<BR> -<BR> RVA0911H413A<BR> RVG0707V100A<BR> RVA0607V(H)306A<BR> RVA1214H213A<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 3104B<BR> 3104C<BR> 3104F<BR> 3104H<BR> -<BR> 3104M<BR> 3104P<BR> 3104S<BR> 3104W<BR> 3104X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> EVMQ0G<BR> EVMQIG<BR> EVMQ3G<BR> EVMS0G<BR> EVMQ0G<BR> EVMG0G<BR> -<BR> -<BR> -<BR> EVMK4GA00B<BR> EVM30GA00B<BR> EVMK0GA00B<BR> EVM38GA00B<BR> EVMB6<BR> EVLQ0<BR> -<BR> EVMMSG<BR> EVMMBG<BR> EVMMAG<BR> -<BR> -<BR> EVMMCS<BR> -<BR> -<BR> -<BR> -<BR> -<BR> EVMM1<BR> -<BR> -<BR> EVMM0<BR> -<BR> -<BR> EVMM3<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> 62-3-1<BR> 62-1-2<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> 67R<BR> -<BR> 67P<BR> -<BR> -<BR> -<BR> -<BR> 67X<BR> 63V<BR> 63S<BR> 63M<BR> -<BR> -<BR> 63H<BR> 63P<BR> -<BR> -<BR> 63X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> RJ/RJR50<BR> RJ/RJR50<BR> RJ/RJR50<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> </TR> </TABLE> <P>&nbsp;<P> <TABLE BORDER=0 CELLSPACING=1 CELLPADDING=3> <TR> <TD COLSPAN=7> <FONT color="#0000FF" SIZE=4 FACE=ARIAL><B>SMD TRIM-POT CROSS REFERENCE</B></FONT> <P> <FONT SIZE=4 FACE=ARIAL><B>MULTI-TURN</B></FONT> </TD> </TR> <TR> <TD> <FONT SIZE=3 FACE=ARIAL><B>BOURNS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>TOCOS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>AUX/KYOCERA</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3224G<BR> 3224J<BR> 3224W<BR> 3269P<BR> 3269W<BR> 3269X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 44G<BR> 44J<BR> 44W<BR> 84P<BR> 84W<BR> 84X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> ST63Z<BR> ST63Y<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> ST5P<BR> ST5W<BR> ST5X<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> -<BR> -<BR> -<BR> -<BR></FONT> </TD> </TR> <TR> <TD COLSPAN=7>&nbsp; </TD> </TR> <TR> <TD COLSPAN=7> <FONT SIZE=4 FACE=ARIAL><B>SINGLE TURN</B></FONT> </TD> </TR> <TR> <TD> <FONT SIZE=3 FACE=ARIAL><B>BOURNS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>BI&nbsp;TECH</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>DALE-VISHAY</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PHILIPS/MEPCO</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>PANASONIC</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>TOCOS</B></FONT> </TD> <TD> <FONT SIZE=3 FACE=ARIAL><B>AUX/KYOCERA</B></FONT> </TD> </TR> <TR> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 3314G<BR> 3314J<BR> 3364A/B<BR> 3364C/D<BR> 3364W/X<BR> 3313G<BR> 3313J<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> 23B<BR> 23A<BR> 21X<BR> 21W<BR> -<BR> 22B<BR> 22A<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> ST5YL/ST53YL<BR> ST5YJ/5T53YJ<BR> ST-23A<BR> ST-22B<BR> ST-22<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> ST-4B<BR> ST-4A<BR> -<BR> -<BR> -<BR> ST-3B<BR> ST-3A<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> EVM-6YS<BR> EVM-1E<BR> EVM-1G<BR> EVM-1D<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> G4B<BR> G4A<BR> TR04-3S1<BR> TRG04-2S1<BR> -<BR> -<BR> -<BR></FONT> </TD> <TD BGCOLOR="#cccccc" ALIGN=CENTER><FONT FACE=ARIAL SIZE=3> -<BR> -<BR> DVR-43A<BR> CVR-42C<BR> CVR-42A/C<BR> -<BR> -<BR></FONT> </TD> </TR> </TABLE> <P> <FONT SIZE=4 FACE=ARIAL><B>ALT =&nbsp;ALTERNATE</B></FONT> <P> &nbsp; <P> </td> </tr> </table> <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> >NAME >VALUE <b>RESISTOR</b> wave soldering<p> >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b> >NAME >VALUE <b>RESISTOR</b><p> wave soldering >NAME >VALUE <b>RESISTOR</b><p> Source: http://download.siliconexpert.com/pdfs/2005/02/24/Semi_Ap/2/VSH/Resistor/dcrcwfre.pdf >NAME >VALUE <b>RESISTOR</b> wave soldering<p> Source: http://download.siliconexpert.com/pdfs/2005/02/24/Semi_Ap/2/VSH/Resistor/dcrcwfre.pdf >NAME >VALUE <b>RESISTOR</b><p> MELF 0.10 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.12 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.10 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.12 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> type 0204, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0204, grid 7.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0204, grid 2.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 10 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 12 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 15mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 2.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 7.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0309, grid 10mm >NAME >VALUE <b>RESISTOR</b><p> type 0309, grid 12.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0309, grid 2.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0411, grid 12.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0411, grid 15 mm >NAME >VALUE <b>RESISTOR</b><p> type 0411, grid 3.81 mm >NAME >VALUE <b>RESISTOR</b><p> type 0414, grid 15 mm >NAME >VALUE <b>RESISTOR</b><p> type 0414, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0617, grid 17.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0617, grid 22.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0617, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0922, grid 22.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0613, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0613, grid 15 mm >NAME >VALUE <b>RESISTOR</b><p> type 0817, grid 22.5 mm >NAME >VALUE 0817 <b>RESISTOR</b><p> type 0817, grid 6.35 mm >NAME >VALUE 0817 <b>RESISTOR</b><p> type V234, grid 12.5 mm >NAME >VALUE <b>RESISTOR</b><p> type V235, grid 17.78 mm >NAME >VALUE <b>RESISTOR</b><p> type V526-0, grid 2.5 mm >NAME >VALUE <b>CECC Size RC2211</b> Reflow Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC2211</b> Wave Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC3715</b> Reflow Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC3715</b> Wave Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC6123</b> Reflow Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC6123</b> Wave Soldering<p> source Beyschlag >NAME >VALUE <b>RESISTOR</b><p> type 0922, grid 7.5 mm >NAME >VALUE 0922 <b>RESISTOR</b><p> type RDH, grid 15 mm >NAME >VALUE RDH <b>Mini MELF 0102 Axial</b> >NAME >VALUE <b>RESISTOR</b> chip<p> Source: http://www.vishay.com/docs/20008/dcrcw.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RBR52<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RBR53<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RBR54<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RBR55<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RBR56<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RNC55<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Bulk Metal® Foil Technology</b>, Tubular Axial Lead Resistors, Meets or Exceeds MIL-R-39005 Requirements<p> MIL SIZE RNC60<br> Source: VISHAY .. vta56.pdf >NAME >VALUE <b>Package 4527</b><p> Source: http://www.vishay.com/docs/31059/wsrhigh.pdf >NAME >VALUE <b>Wirewound Resistors, Precision Power</b><p> Source: VISHAY wscwsn.pdf >NAME >VALUE <b>Wirewound Resistors, Precision Power</b><p> Source: VISHAY wscwsn.pdf >NAME >VALUE <b>Wirewound Resistors, Precision Power</b><p> Source: VISHAY wscwsn.pdf >NAME >VALUE <b>Wirewound Resistors, Precision Power</b><p> Source: VISHAY wscwsn.pdf >NAME >VALUE <b>Wirewound Resistors, Precision Power</b><p> Source: VISHAY wscwsn.pdf >NAME >VALUE <b>Wirewound Resistors, Precision Power</b><p> Source: VISHAY wscwsn.pdf >NAME >VALUE <b>CRCW1218 Thick Film, Rectangular Chip Resistors</b><p> Source: http://www.vishay.com .. dcrcw.pdf >NAME >VALUE <b>Chip Monolithic Ceramic Capacitors</b> Medium Voltage High Capacitance for General Use<p> Source: http://www.murata.com .. GRM43DR72E224KW01.pdf >NAME >VALUE >NAME >VALUE <B>RESISTOR</B>, European symbol PCB Edge >NAME >VALUE >NAME >VALUE Conn Micro USB Type B RCP 5 POS 0.65mm Solder RA SMD 5 Terminal 1 Port T/R <b>Description:</b> Silicon Labs Busy Bee QFN20 Package.<br/> >NAME <b>Manufacturer Part #:</b> EFM8BB10F(2/4/8)G-A-QFN20<br/> <b>Manufacturer:</b> Silicon Labs<br/> <b>Description:</b> Busy Bee 8-bit Microcontrollers - MCU (2/4/8)kB / (256/512)B RAM 12b ADC <br/> !RST!/C2CK C2D/P2.7 GND P0.0 P0.1 P0.2 P0.3 P0.4 P0.5 P0.6 P0.7 P1.0 P1.1 P1.2 P1.3 P1.7 P1.5 P1.6 VDD >NAME >VALUE <b>Manufacturer Part #:</b> EFM8BB10F(2/4/8)G-A-QFN20<br/> <b>Manufacturer:</b> Silicon Labs<br/> <b>Description:</b> Busy Bee 8-bit Microcontrollers - MCU (2/4/8)kB / (256/512)B RAM 12b ADC <br/> <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> chip >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm, outline 2.4 x 4.4 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm, outline 2.5 x 5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm, outline 3 x 5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm, outline 4 x 5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm, outline 5 x 5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm, outline 6 x 5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 mm + 5 mm, outline 2.4 x 7 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 + 5 mm, outline 2.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 + 5 mm, outline 3.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 + 5 mm, outline 4.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 2.5 + 5 mm, outline 5.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 2.4 x 4.4 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 2.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 4.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 3 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 5.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 7.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> Horizontal, grid 5 mm, outline 7.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 7.5 mm, outline 3.2 x 10.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 7.5 mm, outline 4.2 x 10.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 7.5 mm, outline 5.2 x 10.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 10.2 mm, outline 4.3 x 13.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 10.2 mm, outline 5.4 x 13.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 10.2 mm, outline 6.4 x 13.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 10.2 mm + 15.2 mm, outline 6.2 x 18.4 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 15 mm, outline 5.4 x 18.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 15 mm, outline 6.4 x 18.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 15 mm, outline 7.2 x 18.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 15 mm, outline 8.4 x 18.3 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 15 mm, outline 9.1 x 18.2 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 22.5 mm, outline 6.2 x 26.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 22.5 mm, outline 7.4 x 26.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 22.5 mm, outline 8.7 x 26.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 22.5 mm, outline 10.8 x 26.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 22.5 mm, outline 11.3 x 26.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 27.5 mm, outline 9.3 x 31.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 27.5 mm, outline 11.3 x 31.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 27.5 mm, outline 13.4 x 31.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 27.5 mm, outline 20.5 x 31.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 32.5 mm, outline 13.7 x 37.4 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 32.5 mm, outline 16.2 x 37.4 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 32.5 mm, outline 18.2 x 37.4 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 37.5 mm, outline 19.2 x 41.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 37.5 mm, outline 20.3 x 41.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 5 mm, outline 3.5 x 7.5 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 37.5 mm, outline 15.5 x 41.8 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 7.5 mm, outline 6.3 x 10.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 27.5 mm, outline 15.4 x 31.6 mm >NAME >VALUE <b>CAPACITOR</b><p> grid 27.5 mm, outline 17.3 x 31.6 mm >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 0204 Reflow solder</b><p> Metric Code Size 1005 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 0603 Reflow solder</b><p> Metric Code Size 1608 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 0805 Reflow solder</b><p> Metric Code Size 2012 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 1206 Reflow solder</b><p> Metric Code Size 3216 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 1210 Reflow solder</b><p> Metric Code Size 3225 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 1812 Reflow solder</b><p> Metric Code Size 4532 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 1825 Reflow solder</b><p> Metric Code Size 4564 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 2220 Reflow solder</b><p> Metric Code Size 5650 >NAME >VALUE <b>Ceramic Chip Capacitor KEMET 2225 Reflow solder</b><p> Metric Code Size 5664 >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> chip >NAME >VALUE <b>RESISTOR</b><p> chip, wave soldering >NAME >VALUE <b>RESISTOR</b><p> MELF 0.10 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.12 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.10 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.12 W >NAME >VALUE <b>RESISTOR</b><p> MELF 0.25 W >NAME >VALUE <b>RESISTOR</b><p> type 0204, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0204, grid 7.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0204, grid 2.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 10 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 12 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 15mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 2.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0207, grid 7.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0309, grid 10mm >NAME >VALUE <b>RESISTOR</b><p> type 0309, grid 12.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0309, grid 2.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0411, grid 12.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0411, grid 15 mm >NAME >VALUE <b>RESISTOR</b><p> type 0411, grid 3.81 mm >NAME >VALUE <b>RESISTOR</b><p> type 0414, grid 15 mm >NAME >VALUE <b>RESISTOR</b><p> type 0414, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0617, grid 17.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0617, grid 22.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0617, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0922, grid 22.5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0613, grid 5 mm >NAME >VALUE <b>RESISTOR</b><p> type 0613, grid 15 mm >NAME >VALUE <b>RESISTOR</b><p> type 0817, grid 22.5 mm >NAME >VALUE 0817 <b>RESISTOR</b><p> type 0817, grid 6.35 mm >NAME >VALUE 0817 <b>RESISTOR</b><p> type V234, grid 12.5 mm >NAME >VALUE <b>RESISTOR</b><p> type V235, grid 17.78 mm >NAME >VALUE <b>RESISTOR</b><p> type V526-0, grid 2.5 mm >NAME >VALUE <b>CECC Size RC2211</b> Reflow Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC2211</b> Wave Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC3715</b> Reflow Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC3715</b> Wave Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC6123</b> Reflow Soldering<p> source Beyschlag >NAME >VALUE <b>CECC Size RC6123</b> Wave Soldering<p> source Beyschlag >NAME >VALUE <b>RESISTOR</b><p> type 0922, grid 7.5 mm >NAME >VALUE 0922 <b>RESISTOR</b><p> type RDH, grid 15 mm >NAME >VALUE RDH <b>Mini MELF 0102 Axial</b> >NAME >VALUE >NAME >VALUE >NAME >VALUE <B>CAPACITOR</B>, European symbol <B>RESISTOR</B>, European symbol <b>FTDI (TM) CHIP</b> Future Technology Devices International Ltd.<p> http://www.ftdichip.com <b>SSOP-16</b><p> Auto generated by <i>make-symbol-device-package-bsdl.ulp Rev. 43</i><br> Source: <a href="http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT230X.pdf"> Data sheet </a> >NAME >VALUE <b>QFN-16 4 x 4 mm</b><p> Source: <a href="http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT230X.pdf"> Data sheet </a> >NAME >VALUE >NAME >VALUE <b>USB to BASIC UART IC</b><p> Auto generated by <i>make-symbol-device-package-bsdl.ulp Rev. 43</i><br> Source: <a href="http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT230X.pdf"> Data sheet </a> <b>Burr-Brown Components</b><p> <author>Created by librarian@cadsoft.de</author> <b>Smal Outline Transistor</b> >NAME >VALUE <b>DPAC</b> >NAME >VALUE >NAME >VALUE <b>800mA and 1A Low Dropout (LDO) Positive Regulator</b><p> 1.8V, 2.5V, 2.85V, 3.3V, 5V, and Adj >NAME >VALUE >NAME >VALUE LOW POWER HIGH-SIDE CURRENT MONITORS <b>Test Pins/Pads</b><p> Cream on SMD OFF.<br> new: Attribute TP_SIGNAL_NAME<br> <author>Created by librarian@cadsoft.de</author> <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME <b>TEST PAD</b> >NAME >VALUE >TP_SIGNAL_NAME >NAME >TP_SIGNAL_NAME <b>TEST PIN</b> <b>Pin Header Connectors</b><p> <author>Created by librarian@cadsoft.de</author> <b>PIN HEADER</b> >NAME >VALUE <b>PIN HEADER</b> >NAME >VALUE >NAME >VALUE <b>PIN HEADER</b> ================================================ FILE: nsis/.gitignore ================================================ *.exe ================================================ FILE: nsis/go.bat ================================================ copy /Y ..\c\build\i2ccl.exe copy /Y ..\python\samples\dist\i2cgui.exe "C:\Program Files\NSIS\makensis.exe" i2cdriver.nsi copy /Y i2cdriver-installer.exe C:\Users\james\Desktop ================================================ FILE: nsis/i2cdriver.nsi ================================================ # This installs two files, app.exe and logo.ico, creates a start menu shortcut, builds an uninstaller, and # adds uninstall information to the registry for Add/Remove Programs # To get started, put this script into a folder with the two files (app.exe, logo.ico, and license.rtf - # You'll have to create these yourself) and run makensis on it # If you change the names "app.exe", "logo.ico", or "license.rtf" you should do a search and replace - they # show up in a few places. # All the other settings can be tweaked by editing the !defines at the top of this script !define APPNAME "I2CDriver" !define COMPANYNAME "Excamera Labs" !define DESCRIPTION "Utilities for the I2CDriver" # These three must be integers !define VERSIONMAJOR 1 !define VERSIONMINOR 0 !define VERSIONBUILD 0 # These will be displayed by the "Click here for support information" link in "Add/Remove Programs" # It is possible to use "mailto:" links in here to open the email client !define HELPURL "http://i2cdriver.com" # "Support Information" link !define UPDATEURL "http://i2cdriver.com" # "Product Updates" link !define ABOUTURL "http://excamera.com." # "Publisher" link # This is the size (in kB) of all the files copied into "Program Files" !define INSTALLSIZE 700 RequestExecutionLevel admin ;Require admin rights on NT6+ (When UAC is turned on) InstallDir "$PROGRAMFILES\${COMPANYNAME}\${APPNAME}" # rtf or txt file - remember if it is txt, it must be in the DOS text format (\r\n) LicenseData "license.txt" # This will be in the installer/uninstaller's title bar Name "${COMPANYNAME} - ${APPNAME}" Icon "Application.ico" outFile "i2cdriver-installer.exe" !include LogicLib.nsh # Just three pages - license agreement, install location, and installation page license page directory Page instfiles !macro VerifyUserIsAdmin UserInfo::GetAccountType pop $0 ${If} $0 != "admin" ;Require admin rights on NT4+ messageBox mb_iconstop "Administrator rights required!" setErrorLevel 740 ;ERROR_ELEVATION_REQUIRED quit ${EndIf} !macroend function .onInit setShellVarContext all !insertmacro VerifyUserIsAdmin functionEnd section "install" # Files for the install directory - to build the installer, these should be in the same directory as the install script (this file) setOutPath $INSTDIR # Files added here should be removed by the uninstaller (see section "uninstall") file "i2ccl.exe" file "i2cgui.exe" # Add any other files for the install directory (license files, app data, etc) here # Uninstaller - See function un.onInit and section "uninstall" for configuration writeUninstaller "$INSTDIR\uninstall.exe" # Start Menu createDirectory "$SMPROGRAMS\${COMPANYNAME}" createShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\i2cgui.exe" # Desktop Shortcut CreateShortCut "$DESKTOP\I2CDriver.lnk" "$INSTDIR\i2cgui.exe" # Registry information for add/remove programs WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayName" "${COMPANYNAME} - ${APPNAME} - ${DESCRIPTION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "InstallLocation" "$\"$INSTDIR$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayIcon" "$\"$INSTDIR\logo.ico$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "Publisher" "$\"${COMPANYNAME}$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "HelpLink" "$\"${HELPURL}$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLUpdateInfo" "$\"${UPDATEURL}$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "URLInfoAbout" "$\"${ABOUTURL}$\"" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "DisplayVersion" "$\"${VERSIONMAJOR}.${VERSIONMINOR}.${VERSIONBUILD}$\"" WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMajor" ${VERSIONMAJOR} WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "VersionMinor" ${VERSIONMINOR} # There is no option for modifying or repairing the install WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoModify" 1 WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "NoRepair" 1 # Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" "EstimatedSize" ${INSTALLSIZE} Push "$INSTDIR" Call AddToPath sectionEnd # Uninstaller function un.onInit SetShellVarContext all #Verify the uninstaller - last chance to back out MessageBox MB_OKCANCEL "Permanantly remove ${APPNAME}?" IDOK next Abort next: !insertmacro VerifyUserIsAdmin functionEnd section "uninstall" # Remove Start Menu launcher delete "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" # Try to remove the Start Menu folder - this will only happen if it is empty rmDir "$SMPROGRAMS\${COMPANYNAME}" # Remove files delete $INSTDIR\i2ccl.exe delete $INSTDIR\i2cgui.exe # Always delete uninstaller as the last action delete $INSTDIR\uninstall.exe # Try to remove the install directory - this will only happen if it is empty rmDir $INSTDIR # Remove uninstaller information from the registry DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${COMPANYNAME} ${APPNAME}" # Remove the desktop shortcut delete "$DESKTOP\I2CDriver.lnk" # Remove install dir from PATH Push "$INSTDIR" Call un.RemoveFromPath sectionEnd ;-------------------------------------------------------------------- ; Path functions ; ; Based on example from: ; http://nsis.sourceforge.net/Path_Manipulation ; !include "WinMessages.nsh" ; Registry Entry for environment (NT4,2000,XP) ; All users: ;!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' ; Current user only: !define Environ 'HKCU "Environment"' ; AddToPath - Appends dir to PATH ; (does not work on Win9x/ME) ; ; Usage: ; Push "dir" ; Call AddToPath Function AddToPath Exch $0 Push $1 Push $2 Push $3 Push $4 ; NSIS ReadRegStr returns empty string on string overflow ; Native calls are used here to check actual length of PATH ; $4 = RegOpenKey(HKEY_CURRENT_USER, "Environment", &$3) System::Call "advapi32::RegOpenKey(i 0x80000001, t'Environment', *i.r3) i.r4" IntCmp $4 0 0 done done ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) ; RegCloseKey($3) System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" System::Call "advapi32::RegCloseKey(i $3)" IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}" MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" Goto done IntCmp $4 0 +5 ; $4 != NO_ERROR IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND DetailPrint "AddToPath: unexpected error code $4" Goto done StrCpy $1 "" ; Check if already in PATH Push "$1;" Push "$0;" Call StrStr Pop $2 StrCmp $2 "" 0 done Push "$1;" Push "$0\;" Call StrStr Pop $2 StrCmp $2 "" 0 done ; Prevent NSIS string overflow StrLen $2 $0 StrLen $3 $1 IntOp $2 $2 + $3 IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";") IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0 DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}" MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}." Goto done ; Append dir to PATH DetailPrint "Add to PATH: $0" StrCpy $2 $1 1 -1 StrCmp $2 ";" 0 +2 StrCpy $1 $1 -1 ; remove trailing ';' StrCmp $1 "" +2 ; no leading ';' StrCpy $0 "$1;$0" WriteRegExpandStr ${Environ} "PATH" $0 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 done: Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd ; StrStr - find substring in a string ; ; Usage: ; Push "this is some string" ; Push "some" ; Call StrStr ; Pop $0 ; "some string" !macro StrStr un Function ${un}StrStr Exch $R1 ; $R1=substring, stack=[old$R1,string,...] Exch ; stack=[string,old$R1,...] Exch $R2 ; $R2=string, stack=[old$R2,old$R1,...] Push $R3 Push $R4 Push $R5 StrLen $R3 $R1 StrCpy $R4 0 ; $R1=substring, $R2=string, $R3=strlen(substring) ; $R4=count, $R5=tmp loop: StrCpy $R5 $R2 $R3 $R4 StrCmp $R5 $R1 done StrCmp $R5 "" done IntOp $R4 $R4 + 1 Goto loop done: StrCpy $R1 $R2 "" $R4 Pop $R5 Pop $R4 Pop $R3 Pop $R2 Exch $R1 ; $R1=old$R1, stack=[result,...] FunctionEnd !macroend !insertmacro StrStr "" !insertmacro StrStr "un." ; RemoveFromPath - Removes dir from PATH ; ; Usage: ; Push "dir" ; Call RemoveFromPath Function un.RemoveFromPath Exch $0 Push $1 Push $2 Push $3 Push $4 Push $5 Push $6 ReadRegStr $1 ${Environ} "PATH" StrCpy $5 $1 1 -1 StrCmp $5 ";" +2 StrCpy $1 "$1;" ; ensure trailing ';' Push $1 Push "$0;" Call un.StrStr Pop $2 ; pos of our dir StrCmp $2 "" done DetailPrint "Remove from PATH: $0" StrLen $3 "$0;" StrLen $4 $2 StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove StrCpy $3 "$5$6" StrCpy $5 $3 1 -1 StrCmp $5 ";" 0 +2 StrCpy $3 $3 -1 ; remove trailing ';' WriteRegExpandStr ${Environ} "PATH" $3 SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 done: Pop $6 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 FunctionEnd ================================================ FILE: nsis/license.txt ================================================ BSD 3-Clause License Copyright (c) 2019, James Bowman All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: python/.gitignore ================================================ _build/ build/ dist/ i2cdriver.egg-info/ *.csv ================================================ FILE: python/EDS.py ================================================ """ Drivers for electricdollarstore I2C parts """ import struct import time import datetime class Dig2: """ DIG2 is a 2-digit 7-segment LED display """ def __init__(self, i2, a = 0x14): self.i2 = i2 self.a = a def raw(self, b0, b1): """ Set all 8 segments from the bytes b0 and b1 """ self.i2.regwr(self.a, 0, struct.pack("BB", b0, b1)) def hex(self, b): """ Display a hex number 0-0xff """ self.i2.regwr(self.a, 1, b) def dec(self, b): """ Display a decimal number 00-99 """ self.i2.regwr(self.a, 2, b) def dp(self, p0, p1): """ Set the state the decimal point indicators """ self.i2.regwr(self.a, 3, (p1 << 1) | p0) def brightness(self, b): """ Set the brightness from 0 (off) to 255 (maximum) """ self.i2.regwr(self.a, 4, b) class LED: """ LED is an RGB LED """ def __init__(self, i2, a = 0x08): self.i2 = i2 self.a = a def rgb(self, r, g, b, t = 0): """ Set the color to (r,g,b). Each is a byte 0-255. If t is nonzero, the change happens over t/30 seconds. For example if t is 15 the color fades over a half-second. """ if t == 0: self.i2.start(self.a, 0) self.i2.regwr(self.a, 0, bytes([r, g, b])) else: self.i2.start(self.a, 0) self.i2.regwr(self.a, 1, bytes([r, g, b, t])) def hex(self, hhh, t = 0): """ Set the color to hhh, a 24-bit RGB color. If t is nonzero, the change happens over t/30 seconds. For example if t is 15 the color fades over a half-second. """ r = (hhh >> 16) & 0xff g = (hhh >> 8) & 0xff b = hhh & 0xff self.rgb(r, g, b, t) class Pot: """ POT is an analog knob potentiometer """ def __init__(self, i2, a = 0x28): self.i2 = i2 self.a = a def raw(self): """ Return the current knob rotation as a 16-bit integer. """ return self.i2.regrd(self.a, 0, "H") def rd(self, r): """ Return the current knob rotation, scaled to the range 0 .. r inclusive. For example rd(100) returns a value in the range 0 to 100. """ return self.i2.regrd(self.a, r) class Beep: """ BEEP is a beeper """ def __init__(self, i2, a = 0x30): self.i2 = i2 self.a = a def beep(self, dur, note): """ Play a note. dur is the duration in milliseconds, 0-255. note is a MIDI note in the range 21-127 inclusive. """ self.i2.regwr(self.a, dur, note) class Remote: """ REMOTE is a NEC IR code receiver / decoder """ def __init__(self, i2, a = 0x60): self.i2 = i2 self.a = a def key(self): """ For the electricdollarstore IR transmitter. If there is a code in the queue, return its character code. The layout of the remote is p c n < > ' ' - + = 0 % & 1 2 3 4 5 6 7 8 9 If there is no IR code in the queue, return None. """ r = self.i2.regrd(self.a, 0) if r != 0: return chr(r) def raw(self): """ If there is a code in the queue, return a tuple containing the four-byte code, and a timestamp. If there is no IR code in the queue, return None. """ r = self.i2.regrd(self.a, 1, "4BH") if r[:4] != (0xff, 0xff, 0xff, 0xff): age_in_ms = r[4] return (r[:4], time.time() - age_in_ms * .001) else: return None class Temp: """ TEMP is a LM75B temperature sesnor """ def __init__(self, i2, a = 0x48): self.i2 = i2 self.a = a def reg(self, r): return self.i2.regrd(self.a, r, ">h") def read(self): """ Return the current temperature in Celsius """ return (self.reg(0) >> 5) * 0.125 class EPROM: """ EPROM is a CAT24C512 512 Kbit (64 Kbyte) flash memory """ def __init__(self, i2, a = 0x50): self.i2 = i2 self.a = a def write(self, addr, data): """ Write data to EPROM, starting at address addr """ for i in range(0, len(data), 128): self.i2.start(self.a, 0) self.i2.write(struct.pack(">H", addr + i)) self.i2.write(data[i:i + 128]) self.i2.stop() while self.i2.start(self.a, 0) == False: pass def read(self, addr, n): """ Read n bytes from the EPROM, starting at address addr """ self.i2.start(self.a, 0) self.i2.write(struct.pack(">H", addr)) self.i2.start(self.a, 1) r = self.i2.read(n) self.i2.stop() return r self.i2.stop() class Clock: """ CLOCK is a HT1382 I2C/3-Wire Real Time Clock with a 32 kHz crystal """ def __init__(self, i2, a = 0x68): self.i2 = i2 self.a = a def set(self, t = None): if t is None: t = datetime.datetime.now() def bcd(x): return (x % 10) + 16 * (x // 10) self.i2.regwr(self.a, 7, 0) self.i2.regwr(self.a, 6, bcd(t.year % 100)) self.i2.regwr(self.a, 5, 1 + t.weekday()) self.i2.regwr(self.a, 4, bcd(t.month)) self.i2.regwr(self.a, 3, bcd(t.day)) self.i2.regwr(self.a, 2, 0x80 | bcd(t.hour)) # use 24-hour mode self.i2.regwr(self.a, 1, bcd(t.minute)) self.i2.regwr(self.a, 0, bcd(t.second)) def read(self): self.i2.start(self.a, 0) self.i2.write([0]) self.i2.stop() self.i2.start(self.a, 1) (ss,mm,hh,dd,MM,ww,yy) = (struct.unpack("7B", self.i2.read(7))) self.i2.stop() def dec(x): return (x % 16) + 10 * (x // 16) return datetime.datetime( 2000 + dec(yy), dec(MM), dec(dd), dec(hh & 0x7f), dec(mm), dec(ss)) def dump(self): self.i2.start(self.a, 0) self.i2.write([0]) self.i2.stop() self.i2.start(self.a, 1) print(list(self.i2.read(16))) self.i2.stop() class Magnet: """ MAGNET is an ST LIS3MDL 3-axis magnetometer """ def __init__(self, i2, a = 0x1c): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x22, 0) # CTRL_REG3 operating mode 0: continuous conversion def rd(self): """ Read the measurement STATUS_REG and OUT_X,Y,Z """ return self.i2.regrd(self.a, 0x27, "`_ is an easy-to-use, open source tool for controlling I²C devices over USB. It works with Windows, Mac, and Linux, and has a built-in color screen that shows a live "dashboard" of all the I²C activity. .. toctree:: :maxdepth: 2 :caption: Contents: The I²CDriver User Guide has complete information on the hardware: https://i2cdriver.com/i2cdriver.pdf System Requirements =================== Because it is a pure Python module, ``i2cdriver`` can run on any system supported by ``pyserial``. This includes: - Windows 7 or 10 - Mac OS - Linux, including all Ubuntu distributions Both Python 2.7 and 3.x are supported. Installation ------------ The ``i2cdriver`` package can be installed from PyPI using ``pip``:: $ pip install i2cdriver Quick start ----------- To connect to the I2CDriver and scan the bus for connected devices:: >>> import i2cdriver >>> i2c = i2cdriver.I2CDriver("/dev/ttyUSB0") >>> i2c.scan() -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1C -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- [28, 72, 104] To read the temperature in Celsius from a connected LM75 sensor: >>> d=i2cdriver.EDS.Temp(i2c) >>> d.read() 17.875 >>> d.read() 18.0 The User Guide at https://i2cdriver.com has more examples. Module Contents --------------- .. autoclass:: i2cdriver.I2CDriver :member-order: bysource :members: setspeed, setpullups, scan, reset, start, read, write, stop, regwr, regrd, getstatus, monitor .. autoclass:: i2cdriver.START .. autoclass:: i2cdriver.STOP .. autoclass:: i2cdriver.BYTE ================================================ FILE: python/docs/requirements.txt ================================================ pyserial ================================================ FILE: python/go ================================================ set -e python setup.py install # --user # python samples/i2cgui.py /dev/ttyUSB0 make -f Makefile.sphinx latexpdf exit echo Python3: python3 ./confirm.py 1 echo Python2: python2 ./confirm.py 1 # ./thrash.py 3 ./eve.py 9999 python3 ./watch.py ================================================ FILE: python/i2cdriver.py ================================================ import sys import serial import time import struct from collections import OrderedDict __version__ = '1.0.1' PYTHON2 = (sys.version_info < (3, 0)) import EDS class I2CTimeout(Exception): pass class InternalState(OrderedDict): def __repr__(self): return "".join(["%8s %4x\n" % (k, v) for (k, v) in self.items()]) class _I2CEvent: def rrw(self): return ["WRITE", "READ"][self.rw] def rack(self): return ["NACK", "ACK"][self.ack] class START(_I2CEvent): def __init__(self, addr, rw, ack): self.addr = addr self.rw = rw self.ack = ack def __repr__(self): return "" % (self.addr, self.rrw(), self.rack()) def dump(self, f, fmt): if fmt == "csv": f.writerow(("START", self.rrw(), str(self.addr), self.rack())) else: assert False, "unsupported format" def __eq__(self, other): return (self.addr, self.rw, self.ack) == (other.addr, other.rw, other.ack) class STOP(_I2CEvent): def __repr__(self): return "" def dump(self, f, fmt): if fmt == "csv": f.writerow(("STOP", None, None, None)) else: assert False, "unsupported format" def __eq__(self, other): return isinstance(other, STOP) class BYTE(_I2CEvent): def __init__(self, b, rw, ack): self.b = b self.rw = rw self.ack = ack def __repr__(self): return "<%s 0x%02x %s>" % (self.rrw(), self.b, self.rack()) def dump(self, f, fmt): if fmt == "csv": f.writerow(("BYTE", self.rrw(), str(self.b), self.rack())) else: assert False, "unsupported format" def __eq__(self, other): return (self.b, self.rw, self.ack) == (other.b, other.rw, other.ack) class I2CDriver: """ A connected I2CDriver. :param port: The USB port to connect to :type port: str :param reset: Issue an I2C bus reset on connection :type reset: bool After connection, the following object variables reflect the current values of the I2CDriver. They are updated by calling :py:meth:`getstatus`. :ivar product: product code e.g. 'i2cdriver1' or 'i2cdriverm' :ivar serial: serial string of I2CDriver :ivar uptime: time since I2CDriver boot, in seconds :ivar voltage: USB voltage, in V :ivar current: current used by attached device, in mA :ivar temp: temperature, in degrees C :ivar scl: state of SCL :ivar sda: state of SDA :ivar speed: current device speed in KHz (100 or 400) :ivar mode: IO mode (I2C or bitbang) :ivar pullups: programmable pullup enable pins :ivar ccitt_crc: CCITT-16 CRC of all transmitted and received bytes """ def __init__(self, port = "/dev/ttyUSB0", reset = True): """ Connect to a hardware i2cdriver. :param port: The USB port to connect to :type port: str :param reset: Issue an I2C bus reset on connection :type reset: bool """ self.ser = serial.Serial(port, 1000000, timeout = 1) # May be in capture or monitor mode, send char and wait for 50 ms self.ser.write(b'@') time.sleep(.050) # May be waiting up to 64 bytes of input (command code 0xff) self.ser.write(b'@' * 64) self.ser.flush() while self.ser.inWaiting(): self.ser.read(self.ser.inWaiting()) for c in [0x55, 0x00, 0xff, 0xaa]: r = self.__echo(c) if r != c: print('Echo test failed - not attached?') print('Expected %r but received %r' % (c, r)) raise IOError self.getstatus() if reset == "never": return if reset or (self.scl, self.sda) != (1, 1): if self.reset() != 3: raise I2CTimeout("Bus failed to reset - check connected devices") self.getstatus() self.setspeed(100) if PYTHON2: def __ser_w(self, s): if isinstance(s, list) or isinstance(s, tuple): s = "".join([chr(c) for c in s]) self.ser.write(s) else: def __ser_w(self, s): if isinstance(s, list) or isinstance(s, tuple): s = bytes(s) self.ser.write(s) def __echo(self, c): self.__ser_w([ord('e'), c]) r = self.ser.read(1) if PYTHON2: return ord(r[0]) else: return r[0] def setspeed(self, s): """ Set the I2C bus speed. :param s: speed in KHz, either 100 or 400 :type s: int """ assert s in (100, 400) c = {100:b'1', 400:b'4'}[s] self.__ser_w(c) self.speed = s def setpullups(self, s): """ Set the I2CDriver pullup resistors :param s: 6-bit pullup mask """ assert 0 <= s < 64 self.__ser_w([ord('u'), s]) self.pullups = s def scan(self, silent = False): """ Performs an I2C bus scan. If silent is False, prints a map of devices. Returns a list of the device addresses. >>> i2c.scan() -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1C -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- [28, 72, 104] """ self.ser.write(b'd') d = struct.unpack("112c", self.ser.read(112)) if not silent: for a,p in enumerate(d, 8): if p == b"1": st = "%02X" % a else: st = "--" sys.stdout.write(st + " ") if (a % 8) == 7: sys.stdout.write("\n") return [a for a,p in enumerate(d, 8) if p == b"1"] def reset(self): """ Send an I2C bus reset """ self.__ser_w(b'x') return struct.unpack("B", self.ser.read(1))[0] & 3 def start(self, dev, rw): """ Start an I2C transaction :param dev: 7-bit I2C device address :param rw: read (1) or write (0) To write bytes ``[0x12,0x34]`` to device ``0x75``: >>> i2c.start(0x75, 0) >>> i2c.write([0x12,034]) >>> i2c.stop() """ self.__ser_w([ord('s'), (dev << 1) | rw]) return self.ack() def ack(self): a = ord(self.ser.read(1)) if a & 2: raise I2CTimeout return (a & 1) != 0 def read(self, l): """ Read l bytes from the I2C device, and NAK the last byte """ r = [] if l >= 64: bulkpart = (l-1) // 64 for i in range(bulkpart): self.__ser_w([ord('a'), 64]) r.append(self.ser.read(64)) l -= 64 * bulkpart assert 0 <= l <= 64 self.__ser_w([0x80 + l - 1]) r.append(self.ser.read(l)) return b''.join(r) def write(self, bb): """ Write bytes to the selected I2C device :param bb: sequence to write """ ack = True for i in range(0, len(bb), 64): sub = bb[i:i + 64] self.__ser_w([0xc0 + len(sub) - 1]) self.__ser_w(sub) ack = self.ack() return ack def stop(self): """ stop the i2c transaction """ self.ser.write(b'p') def reboot(self): self.__ser_w(b'_') time.sleep(.5) def regrd(self, dev, reg, fmt = "B"): """ Read a register from a device. :param dev: 7-bit I2C device address :param reg: register address 0-255 :param fmt: :py:func:`struct.unpack` format string for the register contents, or an integer byte count If device 0x75 has a 16-bit unsigned big-endian register 102, it can be read with: >>> i2c.regrd(0x75, 102, ">H") 4999 """ if isinstance(fmt, str): r = struct.unpack(fmt, self.regrd(dev, reg, struct.calcsize(fmt))) if len(r) == 1: return r[0] else: return r else: n = fmt if n <= 256: self.__ser_w(b'r' + struct.pack("BBB", dev, reg, n & 0xff)) return self.ser.read(n) else: self.start(dev, 0) self.write([reg]) self.start(dev, 1) r = self.read(n) self.stop() return r def regwr(self, dev, reg, vv): """Write a device's register. :param dev: 7-bit I2C device address :param reg: register address 0-255 :param vv: value to write. Either a single byte, or a sequence To set device 0x34 byte register 7 to 0xA1: >>> i2c.regwr(0x34, 7, 0xa1) If device 0x75 has a big-endian 16-bit register 102 you can set it to 4999 with: >>> i2c.regwr(0x75, 102, struct.pack(">H", 4999)) """ r = self.start(dev, 0) if r: r = self.write(struct.pack("B", reg)) if r: if isinstance(vv, int): vv = struct.pack("B", vv) r = self.write(vv) self.stop() return r def monitor(self, s): """ Enter or leave monitor mode :param s: ``True`` to enter monitor mode, ``False`` to leave """ if s: self.__ser_w(b'm') time.sleep(.1) else: self.__ser_w(b' ') time.sleep(.1) self.__echo(0x40) def introspect(self): self.ser.write(b'J') r = self.ser.read(80) assert len(r) == 80, r body = r[1:-1].decode() # remove [ and ] nn = ( "id ds sp SMB0CF SMB0CN T2 T3 IE EIE1 P0 P0MDIN P0MDOUT P1 P1MDIN P1MDOUT P2 P2MDOUT".split() + "convs".split() ) bb = [int(w, 16) for w in body.split()] assert len(nn) == len(bb) return InternalState(zip(nn, bb)) def restore(self): self.ser.write(b'i') def __repr__(self): return "<%s serial=%s uptime=%d, SCL=%d, SDA=%d>" % ( self.product, self.serial, self.uptime, self.scl, self.sda) def capture_start(self, idle=False, start = START, abyte = BYTE, stop = STOP): """Enter I2C capture mode, capturing I2C transactions. :param idle: If ``True`` the generator returns ``None`` when the bus is idle. If ``False`` the generator does nothing during bus idle. :return: a generator which returns an object for each I2C primitive captured. """ self.__ser_w([ord('c')]) def nstream(): while True: bb = self.ser.read(256) if PYTHON2: for b in bb: yield (ord(b) >> 4) & 0xf yield ord(b) & 0xf else: for b in bb: yield (b >> 4) & 0xf yield b & 0xf def parser(): starting = False rw = 0 for n in nstream(): if n == 0: if idle: yield None elif n == 1: starting = True bits = [] elif n == 2: yield stop() starting = True bits = [] elif n in (8,9,10,11,12,13,14,15): # w(str(n&7)) bits.append(n & 7) if len(bits) == 3: b9 = (bits[0] << 6) | (bits[1] << 3) | bits[2] b8 = (b9 >> 1) ack = b9 & 1 if starting: rw = b8 & 1 yield start(b8 >> 1, rw, ack == 0) starting = False else: yield abyte(b8, rw, ack == 0) bits = [] else: assert 0, "unexpected token" return parser def capture_stop(self): while self.ser.in_waiting: self.ser.read(self.ser.in_waiting) self.__ser_w([ord('c')]) while self.ser.in_waiting: self.ser.read(self.ser.in_waiting) self.__echo(0x40) def capture(self): self.__ser_w([ord('c')]) while 0: b = self.ser.read(1) for c in b: print("%02x" % c) w = sys.stdout.write def nstream(): while 1: for b in self.ser.read(256): yield (b >> 4) & 0xf yield b & 0xf bits = [] for n in nstream(): if n == 0: w(".") elif n == 1: w("S") bits = [] elif n == 2: w("P\n") bits = [] elif n in (8,9,10,11,12,13,14,15): # w(str(n&7)) bits.append(n & 7) if len(bits) == 3: b9 = (bits[0] << 6) | (bits[1] << 3) | bits[2] b8 = (b9 >> 1) ack = b9 & 1 w('%02x%s' % (b8, " !"[ack])) bits = [] else: assert 0, "unexpected token" def getstatus(self): """ Update all status variables """ self.ser.write(b'?') r = self.ser.read(80) body = r[1:-1].decode() # remove [ and ] (self.product, self.serial, uptime, voltage, current, temp, mode, sda, scl, speed, pullups, ccitt_crc) = body.split() self.uptime = int(uptime) self.voltage = float(voltage) self.current = float(current) self.temp = float(temp) self.mode = mode self.scl = int(scl) self.sda = int(sda) self.speed = int(speed) self.pullups = int(pullups, 16) self.ccitt_crc = int(ccitt_crc, 16) return repr(self) ================================================ FILE: python/lm75b.py ================================================ class LM75B: def __init__(self, i2, a = 0x48): self.i2 = i2 self.a = a def reg(self, r): return self.i2.regrd(self.a, r, ">h") def read(self): return (self.reg(0) >> 5) * 0.125 ================================================ FILE: python/samples/EDS-ACCEL.py ================================================ import sys import struct import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.scan() d = EDS.Accel(i2) while True: print("x=%+.3f y=%+.3f z=%+.3f" % d.measurement()) ================================================ FILE: python/samples/EDS-BEEP.py ================================================ import sys import serial import time import struct import random from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1], True) d = EDS.Beep(i2) for note in range(55, 127): print("MIDI note %d" % note) d.beep(100, note) time.sleep(.100) ================================================ FILE: python/samples/EDS-CLOCK.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Clock(i2) d.set() while 1: print(d.read()) time.sleep(1) ================================================ FILE: python/samples/EDS-DIG2.py ================================================ import sys import serial import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Dig2(i2) for i in range(100): d.dec(i) time.sleep(.05) ================================================ FILE: python/samples/EDS-EPROM.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS text = b"""\ CHAPTER 1. Loomings. Call me Ishmael. Some years ago-never mind how long precisely-having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off-then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me. There now is your insular city of the Manhattoes, belted round by wharves as Indian isles by coral reefs-commerce surrounds it with her surf. Right and left, the streets take you waterward. Its extreme downtown is the battery, where that noble mole is washed by waves, and cooled by breezes, which a few hours previous were out of sight of land. Look at the crowds of water-gazers there. Circumambulate the city of a dreamy Sabbath afternoon. Go from Corlears Hook to Coenties Slip, and from thence, by Whitehall, northward. What do you see?-Posted like silent sentinels all around the town, stand thousands upon thousands of mortal men fixed in ocean reveries. Some leaning against the spiles; some seated upon the pier-heads; some looking over the bulwarks of ships from China; some high aloft in the rigging, as if striving to get a still better seaward peep. But these are all landsmen; of week days pent up in lath and plaster-tied to counters, nailed to benches, clinched to desks. How then is this? Are the green fields gone? What do they here? But look! here come more crowds, pacing straight for the water, and seemingly bound for a dive. Strange! Nothing will content them but the extremest limit of the land; loitering under the shady lee of yonder warehouses will not suffice. No. They must get just as nigh the water as they possibly can without falling in. And there they stand-miles of them-leagues. Inlanders all, they come from lanes and alleys, streets and avenues-north, east, south, and west. Yet here they all unite. Tell me, does the magnetic virtue of the needles of the compasses of all those ships attract them thither? Once more. Say you are in the country; in some high land of lakes. Take almost any path you please, and ten to one it carries you down in a dale, and leaves you there by a pool in the stream. There is magic in it. Let the most absent-minded of men be plunged in his deepest reveries-stand that man on his legs, set his feet a-going, and he will infallibly lead you to water, if water there be in all that region. Should you ever be athirst in the great American desert, try this experiment, if your caravan happen to be supplied with a metaphysical professor. Yes, as every one knows, meditation and water are wedded for ever. """ if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.EPROM(i2) d.write(0, text) # Write the block of text starting at address 0 n = len(text) rd = d.read(0, n) # Read it back print(rd.decode()) # Display it ================================================ FILE: python/samples/EDS-LED.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.LED(i2) TEAL = 0x008080 ORANGE = 0xffa500 while 1: time.sleep(1) d.hex(TEAL, 3) time.sleep(1) d.hex(ORANGE, 3) ================================================ FILE: python/samples/EDS-MAGNET.py ================================================ import sys import struct import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Magnet(i2) while 1: print(d.measurement()) ================================================ FILE: python/samples/EDS-POT.py ================================================ import sys import struct import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Pot(i2) while 1: percentage = d.rd(100) r = d.raw() print("%3d/100 raw=%3d" % (percentage, r)) time.sleep(.05) ================================================ FILE: python/samples/EDS-REMOTE.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1], True) i2.setspeed(400) d = EDS.Remote(i2) print("Press a remote button") while 1: k = d.key() if k is not None: print("Key : %r" % k) r = d.raw() if r is not None: (code, timestamp) = r print("Raw code: %02x %02x %02x %02x (time %.2f)" % (code[0], code[1], code[2], code[3], timestamp)) time.sleep(.25) ================================================ FILE: python/samples/EDS-TEMP.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Temp(i2) for i in range(20): celsius = d.read() fahrenheit = celsius * 9/5 + 32 sys.stdout.write("%.1f C %.1f F\n" % (celsius, fahrenheit)) time.sleep(.1) ================================================ FILE: python/samples/EDS-color-compass.py ================================================ """ Demo of a simple combination of parts from Electric Dollar Store: * MAGNET - 3-axis magnetometer * LED - RGB LED This demo takes the compass direction, and uses it to set the LED's color. So as you move the module around, the color changes according to its direction. There is a direction that is pure red, another that is pure green, etc. https://electricdollarstore.com """ import sys from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) magnet = EDS.Magnet(i2) led = EDS.LED(i2) while True: (x, y, z) = magnet.measurement() r = max(0, min(255, (x + 4000) // 32)) g = max(0, min(255, (y + 4000) // 32)) b = max(0, min(255, (z + 4000) // 32)) led.rgb(r, g, b) ================================================ FILE: python/samples/EDS-egg-timer.py ================================================ """ Demo of a simple combination of parts from Electric Dollar Store: * POT - potentiometer * DIG2 - 2-digit display * BEEP - piezo beeper This demo simulates a kitchen egg-timer. Twisting the POT sets a countdown time in seconds, and after it's released the ticker starts counting. When it reaches "00" it flashes and beeps. https://electricdollarstore.com """ import sys import time from i2cdriver import I2CDriver, EDS def millis(): return int(time.time() * 1000) def eggtimer(i2c): pot = EDS.Pot(i2c) beep = EDS.Beep(i2c) digits = EDS.Dig2(i2c) ticking = False v0 = pot.rd(99) next = millis() + 4000 digits.brightness(50) t = 0 while True: v = pot.rd(99) if v0 != v: if v0 < v: beep.beep(2, 80) else: beep.beep(1, 117) ticking = False next = millis() + 1000 v0 = v digits.brightness(255) t = v digits.dec(t) if millis() > next and (t != 0): ticking = True if ticking and millis() > next: next = millis() + 1000 beep.beep(1, 120) if t: t -= 1 else: for i in range(21): digits.brightness(255) beep.beep(75, 107) time.sleep(.1) digits.brightness(0) time.sleep(.05) digits.brightness(50) ticking = False if __name__ == '__main__': i2 = I2CDriver(sys.argv[1], True) eggtimer(i2) ================================================ FILE: python/samples/EDS-take-a-ticket.py ================================================ """ Demo of a simple combination of parts from Electric Dollar Store: * REMOTE - remote control receiver * DIG2 - 2-digit display * BEEP - piezo beeper This demo runs a take-a-ticket display for a store or deli counter. It shows 2-digit "now serving" number, and each time '+' is pressed on the remote it increments the counter and makes a beep, so the next customer can be served. Pressing '-' turns the number back one. https://electricdollarstore.com """ import sys from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) remote = EDS.Remote(i2) beep = EDS.Beep(i2) dig2 = EDS.Dig2(i2) counter = 0 while True: k = remote.key() if k == '+': beep.beep(255, 90) counter = (counter + 1) % 100 if k == '-': beep.beep(100, 80) counter = (counter - 1) % 100 dig2.dec(counter) ================================================ FILE: python/samples/bargraph.py ================================================ """ Example for Bi-Color (Red/Green) 24-Bar Bargraph, based on HT16K33. Available from Adafruit. """ import sys import time import random from i2cdriver import I2CDriver from ht16k33 import HT16K33 class bargraph(HT16K33): def set(self, pix): rr = pix def paint(r, i): """ Paint pixel i """ blk = i // 12 i %= 12 b = i // 4 m = 1 << ((i % 4) + 4 * blk) r[b] |= m red = [0,0,0] grn = [0,0,0] [paint(red, i) for i in range(24) if (pix[i] & 1)] [paint(grn, i) for i in range(24) if (pix[i] & 2)] self.load([red[0], grn[0], red[1], grn[1], red[2], grn[2]]) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d0 = bargraph(i2) for i in range(60): d0.set([random.choice((0,1,2,3)) for i in range(24)]) time.sleep(.08) ================================================ FILE: python/samples/bmp390.py ================================================ # SPDX-FileCopyrightText: 2018 Carter Nelson for Adafruit Industries # # SPDX-License-Identifier: MIT """ `adafruit_bmp3xx` ==================================================== CircuitPython driver from BMP388 Temperature and Barometric Pressure sensor. * Author(s): Carter Nelson Implementation Notes -------------------- **Hardware:** * `Adafruit BMP388 - Precision Barometric Pressure and Altimeter `_ (Product ID: 3966) **Software and Dependencies:** * Adafruit CircuitPython firmware for the supported boards: https://circuitpython.org/downloads * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice """ import struct import time # from micropython import const def const(x): return x __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BMP3XX.git" _BMP388_CHIP_ID = const(0x50) _BMP390_CHIP_ID = const(0x60) # pylint: disable=import-outside-toplevel _REGISTER_CHIPID = const(0x00) _REGISTER_STATUS = const(0x03) _REGISTER_PRESSUREDATA = const(0x04) _REGISTER_TEMPDATA = const(0x07) _REGISTER_CONTROL = const(0x1B) _REGISTER_OSR = const(0x1C) _REGISTER_ODR = const(0x1D) _REGISTER_CONFIG = const(0x1F) _REGISTER_CAL_DATA = const(0x31) _REGISTER_CMD = const(0x7E) _OSR_SETTINGS = (1, 2, 4, 8, 16, 32) # pressure and temperature oversampling settings _IIR_SETTINGS = (0, 2, 4, 8, 16, 32, 64, 128) # IIR filter coefficients class BMP3XX: """Base class for BMP3XX sensor.""" def __init__(self): chip_id = self._read_byte(_REGISTER_CHIPID) if chip_id not in (_BMP388_CHIP_ID, _BMP390_CHIP_ID): raise RuntimeError("Failed to find BMP3XX! Chip ID 0x%x" % chip_id) self._read_coefficients() self.reset() self.sea_level_pressure = 1013.25 self._wait_time = 0.002 # change this value to have faster reads if needed """Sea level pressure in hPa.""" @property def pressure(self): """The pressure in hPa.""" return self._read()[0] / 100 @property def temperature(self): """The temperature in degrees Celsius""" return self._read()[1] @property def altitude(self): """The altitude in meters based on the currently set sea level pressure.""" # see https://www.weather.gov/media/epz/wxcalc/pressureAltitude.pdf return 44307.7 * (1 - (self.pressure / self.sea_level_pressure) ** 0.190284) @property def pressure_oversampling(self): """The pressure oversampling setting.""" return _OSR_SETTINGS[self._read_byte(_REGISTER_OSR) & 0x07] @pressure_oversampling.setter def pressure_oversampling(self, oversample): if oversample not in _OSR_SETTINGS: raise ValueError("Oversampling must be one of: {}".format(_OSR_SETTINGS)) new_setting = self._read_byte(_REGISTER_OSR) & 0xF8 | _OSR_SETTINGS.index( oversample ) self._write_register_byte(_REGISTER_OSR, new_setting) @property def temperature_oversampling(self): """The temperature oversampling setting.""" return _OSR_SETTINGS[self._read_byte(_REGISTER_OSR) >> 3 & 0x07] @temperature_oversampling.setter def temperature_oversampling(self, oversample): if oversample not in _OSR_SETTINGS: raise ValueError("Oversampling must be one of: {}".format(_OSR_SETTINGS)) new_setting = ( self._read_byte(_REGISTER_OSR) & 0xC7 | _OSR_SETTINGS.index(oversample) << 3 ) self._write_register_byte(_REGISTER_OSR, new_setting) @property def filter_coefficient(self): """The IIR filter coefficient.""" return _IIR_SETTINGS[self._read_byte(_REGISTER_CONFIG) >> 1 & 0x07] @filter_coefficient.setter def filter_coefficient(self, coef): if coef not in _IIR_SETTINGS: raise ValueError( "Filter coefficient must be one of: {}".format(_IIR_SETTINGS) ) self._write_register_byte(_REGISTER_CONFIG, _IIR_SETTINGS.index(coef) << 1) def reset(self): """Perform a power on reset. All user configuration settings are overwritten with their default state. """ self._write_register_byte(_REGISTER_CMD, 0xB6) def _read(self): """Returns a tuple for temperature and pressure.""" # OK, pylint. This one is all kinds of stuff you shouldn't worry about. # pylint: disable=invalid-name, too-many-locals # Perform one measurement in forced mode self._write_register_byte(_REGISTER_CONTROL, 0x13) # Wait for *both* conversions to complete while self._read_byte(_REGISTER_STATUS) & 0x60 != 0x60: time.sleep(self._wait_time) # Get ADC values data = self._read_register(_REGISTER_PRESSUREDATA, 6) adc_p = data[2] << 16 | data[1] << 8 | data[0] adc_t = data[5] << 16 | data[4] << 8 | data[3] # datasheet, sec 9.2 Temperature compensation T1, T2, T3 = self._temp_calib pd1 = adc_t - T1 pd2 = pd1 * T2 temperature = pd2 + (pd1 * pd1) * T3 # datasheet, sec 9.3 Pressure compensation P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11 = self._pressure_calib pd1 = P6 * temperature pd2 = P7 * temperature ** 2.0 pd3 = P8 * temperature ** 3.0 po1 = P5 + pd1 + pd2 + pd3 pd1 = P2 * temperature pd2 = P3 * temperature ** 2.0 pd3 = P4 * temperature ** 3.0 po2 = adc_p * (P1 + pd1 + pd2 + pd3) pd1 = adc_p ** 2.0 pd2 = P9 + P10 * temperature pd3 = pd1 * pd2 pd4 = pd3 + P11 * adc_p ** 3.0 pressure = po1 + po2 + pd4 # pressure in hPa, temperature in deg C return pressure, temperature def _read_coefficients(self): """Read & save the calibration coefficients""" coeff = self._read_register(_REGISTER_CAL_DATA, 21) # See datasheet, pg. 27, table 22 coeff = struct.unpack(" self._temp_calib = ( coeff[0] / 2 ** -8.0, # T1 coeff[1] / 2 ** 30.0, # T2 coeff[2] / 2 ** 48.0, ) # T3 self._pressure_calib = ( (coeff[3] - 2 ** 14.0) / 2 ** 20.0, # P1 (coeff[4] - 2 ** 14.0) / 2 ** 29.0, # P2 coeff[5] / 2 ** 32.0, # P3 coeff[6] / 2 ** 37.0, # P4 coeff[7] / 2 ** -3.0, # P5 coeff[8] / 2 ** 6.0, # P6 coeff[9] / 2 ** 8.0, # P7 coeff[10] / 2 ** 15.0, # P8 coeff[11] / 2 ** 48.0, # P9 coeff[12] / 2 ** 48.0, # P10 coeff[13] / 2 ** 65.0, ) # P11 def _read_byte(self, register): """Read a byte register value and return it""" return self._read_register(register, 1)[0] def _read_register(self, register, length): """Low level register reading, not implemented in base class""" raise NotImplementedError() def _write_register_byte(self, register, value): """Low level register writing, not implemented in base class""" raise NotImplementedError() class BMP3XX_I2C(BMP3XX): """Driver for I2C connected BMP3XX. :param ~busio.I2C i2c: The I2C bus the BMP388 is connected to. :param int address: I2C device address. Defaults to :const:`0x77`. but another address can be passed in as an argument **Quickstart: Importing and using the BMP388** Here is an example of using the :class:`BMP3XX_I2C` class. First you will need to import the libraries to use the sensor .. code-block:: python import board import adafruit_bmp3xx Once this is done you can define your `board.I2C` object and define your sensor object .. code-block:: python i2c = board.I2C() # uses board.SCL and board.SDA bmp = adafruit_bmp3xx.BMP3XX_I2C(i2c) Now you have access to the :attr:`temperature` and :attr:`pressure` attributes .. code-block:: python temperature = bmp.temperature pressure = bmp.pressure """ def __init__(self, i2c, address=0x77): from adafruit_bus_device import i2c_device self._i2c = i2c_device.I2CDevice(i2c, address) super().__init__() def _read_register(self, register, length): """Low level register reading over I2C, returns a list of values""" result = bytearray(length) with self._i2c as i2c: i2c.write(bytes([register & 0xFF])) i2c.readinto(result) return result def _write_register_byte(self, register, value): """Low level register writing over I2C, writes one 8-bit value""" with self._i2c as i2c: i2c.write(bytes((register & 0xFF, value & 0xFF))) class BMP3XX_SPI(BMP3XX): """Driver for SPI connected BMP3XX. :param ~busio.SPI spi: SPI device :param ~digitalio.DigitalInOut cs: Chip Select **Quickstart: Importing and using the BMP388** Here is an example of using the :class:`BMP3XX_SPI` class. First you will need to import the libraries to use the sensor .. code-block:: python import board import adafruit_bmp3xx from digitalio import DigitalInOut, Direction Once this is done you can define your `board.SPI` object and define your sensor object .. code-block:: python spi = board.SPI() cs = DigitalInOut(board.D5) bmp = adafruit_bmp3xx.BMP3XX_SPI(spi, cs) Now you have access to the :attr:`temperature` and :attr:`pressure` attributes .. code-block:: python temperature = bmp.temperature pressure = bmp.pressure """ def __init__(self, spi, cs): from adafruit_bus_device import spi_device self._spi = spi_device.SPIDevice(spi, cs) # toggle CS low/high to put BMP3XX in SPI mode with self._spi: time.sleep(0.001) super().__init__() def _read_register(self, register, length): """Low level register reading over SPI, returns a list of values""" result = bytearray(length) with self._spi as spi: # pylint: disable=no-member spi.write(bytes((0x80 | register, 0x00))) spi.readinto(result) return result def _write_register_byte(self, register, value): """Low level register writing over SPI, writes one 8-bit value""" with self._spi as spi: # pylint: disable=no-member spi.write(bytes((register & 0x7F, value & 0xFF))) # from i2cdriver import I2CDriver import sys class BMP3XX_I2CDriver(BMP3XX): """Driver for I2CDriver connected BMP3XX. :param ~busio.I2C i2c: The I2CDriver the BMP388 is connected to. :param int address: I2C device address. Defaults to :const:`0x77`. but another address can be passed in as an argument **Quickstart: Importing and using the BMP388** Here is an example of using the :class:`BMP3XX_I2CDriver` class. First you will need to import the libraries .. code-block:: python from i2cdriver import I2CDriver import adafruit_bmp3xx Once this is done you can connect to the I2CDriver and define the sensor object, e.g. .. code-block:: python i2c = I2CDriver("COM9") bmp = adafruit_bmp3xx.BMP3XX_I2C(i2c) Now you have access to the :attr:`temperature` and :attr:`pressure` attributes .. code-block:: python temperature = bmp.temperature pressure = bmp.pressure """ def __init__(self, i2c, address=0x77): self.i2c = i2c self.a = address super().__init__() def _read_register(self, register, length): """Low level register reading over I2C, returns a list of values""" return self.i2c.regrd(self.a, register, length) def _write_register_byte(self, register, value): """Low level register writing over I2C, writes one 8-bit value""" self.i2c.regwr(self.a, register, value) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = BMP3XX_I2CDriver(i2) d.pressure_oversampling = 32 d.temperature_oversampling = 32 while 1: (pressure, temperature) = d._read() print(f"Pressure: {pressure / 100:.2f} hPa") print(f"Temperature: {temperature:.2f} C") ================================================ FILE: python/samples/bno080.py ================================================ """ Example for BNO080 integrated IMU. Available from Sparkfun. """ import sys import serial import time import struct import random import math from i2cdriver import I2CDriver def hexdump(s): def toprint(c): if 32 <= c < 127: return chr(c) else: return "." def hexline(s): return (" ".join(["%02x" % c for c in s]).ljust(49) + "|" + "".join([toprint(c) for c in s]).ljust(16) + "|") return "\n".join([hexline(s[i:i+16]) for i in range(0, len(s), 16)]) CHANNEL_COMMAND = 0 CHANNEL_EXECUTABLE = 1 CHANNEL_CONTROL = 2 CHANNEL_REPORTS = 3 CHANNEL_WAKE_REPORTS = 4 CHANNEL_GYRO = 5 # All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual # These are used for low level communication with the sensor, on channel 2 SHTP_REPORT_COMMAND_RESPONSE = 0xF1 SHTP_REPORT_COMMAND_REQUEST = 0xF2 SHTP_REPORT_FRS_READ_RESPONSE = 0xF3 SHTP_REPORT_FRS_READ_REQUEST = 0xF4 SHTP_REPORT_PRODUCT_ID_RESPONSE = 0xF8 SHTP_REPORT_PRODUCT_ID_REQUEST = 0xF9 SHTP_REPORT_BASE_TIMESTAMP = 0xFB SHTP_REPORT_SET_FEATURE_COMMAND = 0xFD # All the different sensors and features we can get reports from # These are used when enabling a given sensor SENSOR_REPORTID_ACCELEROMETER = 0x01 SENSOR_REPORTID_GYROSCOPE = 0x02 SENSOR_REPORTID_MAGNETIC_FIELD = 0x03 SENSOR_REPORTID_LINEAR_ACCELERATION = 0x04 SENSOR_REPORTID_ROTATION_VECTOR = 0x05 SENSOR_REPORTID_GRAVITY = 0x06 SENSOR_REPORTID_GAME_ROTATION_VECTOR = 0x08 SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR = 0x09 SENSOR_REPORTID_TAP_DETECTOR = 0x10 SENSOR_REPORTID_STEP_COUNTER = 0x11 SENSOR_REPORTID_STABILITY_CLASSIFIER = 0x13 SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER = 0x1E # Record IDs from figure 29, page 29 reference manual # These are used to read the metadata for each sensor type FRS_RECORDID_ACCELEROMETER = 0xE302 FRS_RECORDID_GYROSCOPE_CALIBRATED = 0xE306 FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED = 0xE309 FRS_RECORDID_ROTATION_VECTOR = 0xE30B # Command IDs from section 6.4, page 42 # These are used to calibrate, initialize, set orientation, tare etc the sensor COMMAND_ERRORS = 1 COMMAND_COUNTER = 2 COMMAND_TARE = 3 COMMAND_INITIALIZE = 4 COMMAND_DCD = 6 COMMAND_ME_CALIBRATE = 7 COMMAND_DCD_PERIOD_SAVE = 9 COMMAND_OSCILLATOR = 10 COMMAND_CLEAR_DCD = 11 CALIBRATE_ACCEL = 0 CALIBRATE_GYRO = 1 CALIBRATE_MAG = 2 CALIBRATE_PLANAR_ACCEL = 3 CALIBRATE_ACCEL_GYRO_MAG = 4 CALIBRATE_STOP = 5 def normalize(v, tolerance=0.00001): mag2 = sum(n * n for n in v) if abs(mag2 - 1.0) > tolerance: mag = math.sqrt(mag2) v = tuple(n / mag for n in v) return v class BNO080: def __init__(self, i2, a = 0x4b): self.i2 = i2 self.a = a self.seqno = [0] * 8 if 1: self.sendPacket(CHANNEL_EXECUTABLE, [1]) time.sleep(0.150) while True: if not self.receivePacket(): break self.setFeature(SENSOR_REPORTID_ROTATION_VECTOR, 50000) def read_quaternion(self): while True: r = self.receivePacket() while r: tag = r[0] r = r[1:] if tag == 0xfb: # print("Time %d" % struct.unpack("I", r[:4])) r = r[4:] elif tag == SHTP_REPORT_COMMAND_RESPONSE: r = r[16:] elif tag == 0xfc: # print("Get Feature Response") r = r[17:] elif tag == SENSOR_REPORTID_ACCELEROMETER: r = r[10:] elif tag == SENSOR_REPORTID_ROTATION_VECTOR: (_,_,_,i,j,k,w,_) = struct.unpack(" 0): if preferred in self.devs: d1 = preferred else: d1 = min(self.devs) try: self.connect(self.devs[d1]) except: del self.devs[d1] d1 = None cb.Set(sorted(self.devs.keys())) if d1 is not None: cb.SetValue(d1) t = threading.Thread(target=ping_thr, args=(self, ), daemon=True) t.start() def start(self, rw): self.sd.start(self.addr, rw) self.started = True self.stop_button.Enable(True) def stop(self, e = None): self.sd.stop() self.started = False self.stop_button.Enable(False) def reset(self, e = None): self.sd.reset() self.started = False def write(self, htc, e): if (self.addr is not None) and htc.GetValue(): vv = [int(c,16) for c in htc.GetValue().split()] self.start(0) self.sd.write(vv) def read(self, e): n = int(self.rxCount.GetValue()) if self.addr is not None: self.start(1) r = self.sd.read(n) bb = struct.unpack("B"*n, r) self.rxVal.SetValue(" ".join(["%02X" % b for b in bb])) self.stop() def devices(self): if sys.platform in ('win32', 'cygwin'): return {pi.device: pi.device for pi in slp.comports()} elif sys.platform == 'darwin': devdir = "/dev/" pattern = "^cu.usbserial-(.*)" else: devdir = "/dev/serial/by-id/" pattern = "^usb-FTDI_FT230X_Basic_UART_(........)-" if not os.access(devdir, os.R_OK): return {} devs = os.listdir(devdir) def filter(d): m = re.match(pattern, d) if m: return (m.group(1), devdir + d) seldev = [filter(d) for d in devs] return dict([d for d in seldev if d]) def connect(self, dev): self.sd = i2cdriver.I2CDriver(dev) [w.Enable(True) for w in self.allw] self.refresh(None) def refresh(self, e): if self.sd and not self.monitor and not self.capture: lowhigh = ["LOW", "HIGH"] self.sd.getstatus() self.label_serial.SetLabel(self.sd.serial) self.label_voltage.SetLabel("%.2f V" % self.sd.voltage) self.label_current.SetLabel("%d mA" % self.sd.current) self.label_temp.SetLabel("%.1f C" % self.sd.temp) self.label_speed.SetSelection({100:0, 400:1}[self.sd.speed]) self.label_pullups.SetStringSelection(pullup_vals[self.sd.pullups & 7]) self.label_sda.SetLabel(lowhigh[self.sd.sda]) self.label_scl.SetLabel(lowhigh[self.sd.scl]) days = self.sd.uptime // (24 * 3600) rem = self.sd.uptime % (24 * 3600) hh = rem // 3600 mm = (rem // 60) % 60 ss = rem % 60; self.label_uptime.SetLabel("%d:%02d:%02d:%02d" % (days, hh, mm, ss)) [d.Enable(True) for d in self.dynamic] if not self.started and (self.sd.sda == 1) and (self.sd.scl == 1): devs = self.sd.scan(True) for i,l in self.heat.items(): self.hot(i, i in devs) def choose_device(self, e): self.connect(self.devs[e.EventObject.GetValue()]) def no_addr(self): [w.Enable(False) for w in self.dev_widgets] def choose_addr(self, e): o = e.EventObject v = o.GetValue() if v: self.addr = int(o.GetLabel(), 16) [w.Enable(True) for w in self.dev_widgets] def check_m(self, e): self.monitor = e.EventObject.GetValue() self.sd.monitor(self.monitor) [d.Enable(not self.monitor) for d in self.dynamic] if self.monitor: [self.hot(i, False) for i in self.heat] def check_c(self, e): global StopCapture cm = e.EventObject.GetValue() # self.sd.monitor(self.monitor) if cm: openFileDialog = wx.FileDialog(self, "CSV dump to file", "", "", "CSV files (*.csv)|*.csv", wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) openFileDialog.ShowModal() self.log_csv = openFileDialog.GetPath() openFileDialog.Destroy() if self.log_csv == u"": e.EventObject.SetValue(False) return StopCapture = False self.sd.dumpcount = 0 t = threading.Thread(target=capture_thr, args=(self.sd, self.log_csv)) t.setDaemon(True) t.start() else: StopCapture = True wx.MessageBox("Capture finished. %d events written to \"%s\"" % (self.sd.dumpcount, self.log_csv), "Message", wx.OK | wx.ICON_INFORMATION) while StopCapture: pass [d.Enable(not cm) for d in self.dynamic] if cm: [self.hot(i, False) for i in self.heat] self.capture = cm def set_speed(self, e): w = e.EventObject s = int(w.GetString(w.GetCurrentSelection())) self.sd.setspeed(s) def set_pullups(self, e): w = e.EventObject s = w.GetString(w.GetCurrentSelection()) code = pullup_vals.index(s) self.sd.setpullups(code | (code << 3)) def hot(self, i, s): l = self.heat[i] if s: l.SetForegroundColour((0,0,0)) l.SetFont(self.addrfonts[1]) else: l.SetForegroundColour((160,) * 3) l.SetFont(self.addrfonts[0]) l.Enable(s) if i == self.addr: [w.Enable(s) for w in self.dev_widgets] if __name__ == '__main__': app = wx.App(0) try: f = Frame(*sys.argv[1:]) f.Show(True) app.MainLoop() except: import sys, traceback xc = traceback.format_exception(*sys.exc_info()) dlg = wx.MessageDialog(None, "".join(xc), "i2cgui Error Trap (%s)" % i2cdriver.__version__, wx.OK | wx.ICON_WARNING) dlg.ShowModal() dlg.Destroy() ================================================ FILE: python/samples/lcd1602.py ================================================ """ Example for LCD1602, in which a PCF8574 I/O expander drives a HD44780. Available from various vendors. Note that the modules require a 5V VCC; they don't function using the 3.3V VCC of I2CDriver. """ import sys import time import struct from i2cdriver import I2CDriver class HD44780: def __init__(self, i2, a = 0x27): self.i2 = i2 self.a = a self.nybble(3) # Enter 4-bit mode self.nybble(3) self.nybble(3) self.nybble(2) self.cmd(0x28) # 2 lines, 5x8 dot matrix self.cmd(0x0c) # display on self.cmd(0x06) # inc cursor to right when writing and don't scroll self.cmd(0x80) # set cursor to row 1, column 1 self.clear() def clear(self): """ Clear the screen """ self.cmd(0x01) time.sleep(.003) def show(self, line, text): """ Send string to LCD. Newline wraps to second line""" self.cmd({0:0x80, 1:0xc0}[line]) for c in text: self.data(ord(c)) def cmd(self, b): self.nybble(b >> 4) self.nybble(b & 0xf) time.sleep(.000053) def data(self, b): self.nybble(b >> 4, 1) self.nybble(b & 0xf, 1) # The PCF8574 outputs are connected to the HD44780 # pins as follows: # P0 RS (0: command, 1: data) # P1 R/W (0: write, 1: read) # P2 Enable/CLK # P3 Backlight control # P4-7 D4-D7 def nybble(self, n, rs = 0): bl = 8 | rs self.port( bl | (n << 4), bl | (n << 4) | 4, bl | (n << 4) ) def port(self, *bb): # Write bytes to port, setting the PCF8574 outputs self.i2.start(self.a, 0) self.i2.write(bb) self.i2.stop() if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = HD44780(i2) d.show(0, "HELLO WORLD") time.sleep(.5) d.show(1, "0123456789012345") ================================================ FILE: python/samples/led8x8.py ================================================ """ Example for 8x8 LED Matrix modules, based on HT16K33. Available from multiple vendors. """ import sys import time from i2cdriver import I2CDriver font = open("cp437-8x8", "rb").read() from ht16k33 import HT16K33 class led8x8(HT16K33): def image(self, bb): """ Set the pixels to the bytes bb """ def swiz(b): bs = [str((b >> n) & 1) for n in range(8)] return int(bs[7] + bs[0] + bs[1] + bs[2] + bs[3] + bs[4] + bs[5] + bs[6], 2) bb = [swiz(b) for b in bb] self.load([b for s in zip(bb,bb) for b in s]) def char(self, c): """ Set the pixels to character c """ n = ord(c) ch = font[n * 8:n * 8 + 8] self.image(ch) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = led8x8(i2) for c in "I2C": d.char(c) time.sleep(1) ================================================ FILE: python/samples/mag3110.py ================================================ """ Example Xtrinsic MAG3110 Three-Axis Digital Magnetometer Breakout available from Sparkfun. """ import sys import struct import time from i2cdriver import I2CDriver, EDS class MAG3110: def __init__(self, i2, a = 0x0e): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x10, 0b00000001) # CTRL_REG1. ACTIVE mode, 80 Hz conversions def rd(self): """ Read the measurement STATUS_REG and OUT_X,Y,Z """ return self.i2.regrd(self.a, 0x00, ">B3h") def measurement(self): """ Wait for a new field reading, return the (x,y,z) """ while True: (status, x, y, z) = self.rd() if status & 8: return (x, y, z) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.scan() d = MAG3110(i2) while 1: print(d.measurement()) ================================================ FILE: python/samples/mux.py ================================================ import sys from i2cdriver import I2CDriver, EDS # Using a TCA9548A Low-Voltage 8-Channel I2C Switch # Three LM75B temperature sensors are connected to # channels 0,1 and 2. All are at address 0x48. class Mux: def __init__(self, i2, a = 0x70): self.i2 = i2 self.a = a def select(self, n): assert n in range(8) self.i2.start(self.a, 0) self.i2.write([1 << n]) self.i2.stop() if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) mux = Mux(i2) sensors = [ (0, EDS.Temp(i2)), (1, EDS.Temp(i2)), (2, EDS.Temp(i2)) ] # Reset all 8 channels for chan in range(8): mux.select(chan) i2.reset() def read(chan, dev): mux.select(chan) celsius = dev.read() return celsius while 1: print(" ".join(["%.1f" % read(chan, dev) for chan,dev in sensors])) ================================================ FILE: python/samples/oled.py ================================================ """ Example for 128X64OLED Module Available from multiple vendors, e.g. DIYMall This example loads the I2CDriver logo onto the display, and flashes it four times. """ import sys import time from PIL import Image, ImageChops from i2cdriver import I2CDriver SETCONTRAST = 0x81 DISPLAYALLON_RESUME = 0xA4 DISPLAYALLON = 0xA5 NORMALDISPLAY = 0xA6 INVERTDISPLAY = 0xA7 DISPLAYOFF = 0xAE DISPLAYON = 0xAF SETDISPLAYOFFSET = 0xD3 SETCOMPINS = 0xDA SETVCOMDETECT = 0xDB SETDISPLAYCLOCKDIV = 0xD5 SETPRECHARGE = 0xD9 SETMULTIPLEX = 0xA8 SETLOWCOLUMN = 0x00 SETHIGHCOLUMN = 0x10 SETSTARTLINE = 0x40 MEMORYMODE = 0x20 COLUMNADDR = 0x21 PAGEADDR = 0x22 COMSCANINC = 0xC0 COMSCANDEC = 0xC8 SEGREMAP = 0xA0 CHARGEPUMP = 0x8D class OLED: def __init__(self, i2, a = 0x3c): self.i2 = i2 self.a = a self.command(DISPLAYOFF) self.command(SETDISPLAYCLOCKDIV, 0x80) # the suggested ratio 0x80 self.command(SETMULTIPLEX, 0x3f) self.command(SETDISPLAYOFFSET, 0) self.command(SETSTARTLINE | 0x0) self.command(CHARGEPUMP, 0x14) self.command(MEMORYMODE, 0) self.command(SEGREMAP | 0x1) self.command(COMSCANDEC) self.command(SETCOMPINS, 0x12) self.command(SETCONTRAST, 0xcf) self.command(SETVCOMDETECT, 0x40) self.command(DISPLAYALLON_RESUME) self.command(NORMALDISPLAY) self.im = Image.new("1", (128,64), 1) self.cls() def command(self, *c): assert(self.i2.start(self.a, 0)) assert(self.i2.write((0,) + c)) self.i2.stop() def image(self, im): for p in range(8): pr = self.im.crop((0,8*p,128,8*p+8)).transpose(Image.ROTATE_270) bb = im.crop((0,8*p,128,8*p+8)).transpose(Image.ROTATE_270) diff = ImageChops.difference(pr, bb) di = diff.getbbox() if di is not None: (x0, y0, x1, y1) = di self.command(COLUMNADDR) self.command(y0) self.command(y1 - 1) self.command(PAGEADDR) self.command(p) self.command(p + 1) self.i2.start(self.a, 0) self.i2.write([0x40]) self.i2.write(bb.tobytes()[y0:y1]) self.i2.stop() self.im = im self.command(DISPLAYON) def cls(self): self.image(Image.new("1", (128,64), 0)) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = OLED(i2) d.image(Image.open("logo.png").convert("1")) for i in range(4): d.command(INVERTDISPLAY) time.sleep(.5) d.command(NORMALDISPLAY) time.sleep(.5) ================================================ FILE: python/samples/pca9685.py ================================================ import sys import time import random import struct from i2cdriver import I2CDriver class PCA9685: def __init__(self, i2, a = 0x40): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x00, 0x20) # auto-increment mode def set(self, channel, t_on, t_off): assert 0 <= channel < 16 assert 0 <= t_on <= 0x1000 assert 0 <= t_off <= 0x1000 self.i2.regwr(self.a, 0x06 + 4 * channel, struct.pack("H", self.i2.read(2)) self.i2.stop() return r def read(self): """ return the joystick (x,y) position. The range is 0-1023. The center position of the joystick is approximately 512. """ # Note: their firmware requires two separate reads return (self.axis(0), self.axis(2)) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = Joystick(i2) while 1: print(d.read()) time.sleep(.1) ================================================ FILE: python/samples/qwiic-keypad.py ================================================ """ Example for Qwiic Keypad Available from Sparkfun. """ import sys import time import struct from i2cdriver import I2CDriver class Keypad: def __init__(self, i2, a = 0x4b): self.i2 = i2 self.a = a def read_ts(self): """ Return (key, timestamp) if pressed, or None. """ self.i2.start(self.a, 1) (k, age_in_ms) = struct.unpack(">BH", self.i2.read(3)) self.i2.stop() if k != 0: return (chr(k), time.time() - age_in_ms * .001) else: return None def read(self): r = self.read_ts() if r: return r[0] else: return None if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = Keypad(i2) while 1: print(d.read()) time.sleep(.1) ================================================ FILE: python/samples/read-temperature.py ================================================ import sys import time from i2cdriver import I2CDriver, LM75B if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = LM75B(i2) for i in range(100): print(d.read()) time.sleep(.1) ================================================ FILE: python/samples/touch.py ================================================ """ Example for MPR121 Capacitive Touch Sensor. Available from multiple vendors. """ import sys import serial import time import struct import random from i2cdriver import I2CDriver class MPR121: def __init__(self, i2, a = 0x5a): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x5e, 0x0c) def read(self): """ Return 12 touch detection flags """ (tb,) = struct.unpack("> i) & 1) for i in range(12)] if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.reset() d = MPR121(i2) while 1: print(d.read()) time.sleep(.1) ================================================ FILE: python/samples/wii.py ================================================ import sys import struct from i2cdriver import I2CDriver # # For details see # https://wiibrew.org/wiki/Wiimote/Extension_Controllers # class Wii: def __init__(self, i2, a = 0x52): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0xf0, 0x55) self.i2.regwr(self.a, 0xfb, 0x00) idcode = (self.rdreg(0xfa, 6)) devices = { bytes([0x01, 0x00, 0xa4, 0x20, 0x01, 0x01]): self.wii_classic_pro, } if idcode in devices: self.rd = devices[idcode] else: raise IOError("Unrecognised device %r" % idcode) def rdreg(self, addr, n): self.i2.start(self.a, 0) self.i2.write([addr]) self.i2.stop() self.i2.start(self.a, 1) r = self.i2.read(n) self.i2.stop() return r def wii_classic_pro(self): b = self.rdreg(0x00, 6) r4 = '. brt b+ bh b- blt bdd bdr'.split() r = {id: 1 & (~b[4] >> i) for i,id in enumerate(r4)} r5 = 'bdu bdl bzr bx ba by bb bzl'.split() r.update({id: 1 & (~b[5] >> i) for i,id in enumerate(r5)}) r.update({ 'lx' : b[0] & 63, 'ly' : b[1] & 63, 'rx' : (((b[0] >> 6) & 3) << 3) | (((b[1] >> 6) & 3) << 1) | (((b[2] >> 7) & 1)), 'ry' : b[2] & 31, 'lt' : (((b[2] >> 5) & 3) << 3) | (((b[3] >> 5) & 7)), 'rt' : b[3] & 31, }) return r if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.scan() d = Wii(i2) while True: print(d.rd()) ================================================ FILE: python/setup.py ================================================ # coding=utf-8 from setuptools import setup LONG = """\ I2CDriver is a tool for controlling, monitoring and capturing I2C from your PC's USB port. It connects as a standard USB serial device, so there are no drivers to install.""" for l in open("i2cdriver.py", "rt"): if l.startswith("__version__"): exec(l) setup(name='i2cdriver', version=__version__, author='James Bowman', author_email='jamesb@excamera.com', url='http://i2cdriver.com', description='I2CDriver is a desktop I2C interface', long_description=LONG, license='GPL', install_requires=['pyserial'], py_modules = [ 'i2cdriver', 'EDS', ], scripts=['samples/i2cgui.py'], project_urls={ 'Documentation': 'https://i2cdriver.readthedocs.io/en/latest/', } ) ================================================ FILE: python/tests/accept.py ================================================ from __future__ import print_function, division import sys import time import struct import random import i2cdriver import unittest DUT = "dut" # grn0 AGG = "agg" # blk1 def bit(b, x): return 1 & (x >> b) def byte(x): return struct.pack("B", x) class TestDUT(unittest.TestCase): def setUp(self): self.i2 = i2cdriver.I2CDriver(DUT) self.ag = i2cdriver.I2CDriver(AGG) def init(self): self.i2.reboot() self.i2.setspeed(400) self.i2.getstatus() return self.i2 def lm75_read(self, i, reg): (tr,) = struct.unpack(">h", i.regrd(0x48, reg, 2)) return tr def lm75_slow_read(self, i, reg): i.start(0x48, 0) i.write(struct.pack("B", reg)) i.start(0x48, 1) (tr,) = struct.unpack(">h", i.read(2)) i.stop() return tr def lm75_write(self, i, reg, v): i.start(0x48, 0) i.write(struct.pack(">Bh", reg, v)) i.stop() def stack0(self): self.s0 = self.i2.introspect() def stacksame(self): s1 = self.i2.introspect() for i in ("ds", "sp"): self.assertEqual(self.s0[i], s1[i]) def confirm(self): # Basic i2c confirmation self.assertEqual(self.lm75_read(self.i2, 2), 0x4b00) def confirm_sampling(self): # Check that analog sampling is happening econvs = { "i2cdriver1" : {0,1,2}, "i2cdriverm" : {0} }[self.i2.product] s = set() while len(s) < len(econvs): s.add(self.i2.introspect()["convs"]) self.assertEqual(s, econvs) def test_temperature(self): # Confirm onboard temperature sensor is reasonable and changing i2 = self.i2 i2.getstatus() onboard = i2.temp external = (self.lm75_read(i2, 0) >> 5) * 0.125 self.assertTrue(abs(onboard - external) < 10) # Wait up to 10 seconds for temperature to change t0 = time.time() while onboard == i2.temp: i2.getstatus() self.assertTrue(time.time() < (t0 + 10)) def test_coldstart(self): i2 = self.init() s = i2.introspect() self.assertEqual(i2.scl, 1) self.assertEqual(i2.sda, 1) def test_scan(self): i2 = self.init() def det(a): r = i2.start(a, 0) i2.stop() return r scan = [det(a) for a in range(128)] e = [(i == 0x48) for i in range(128)] self.assertEqual(scan, e) def test_lm75_reg(self): i2 = self.i2 self.stack0() vals = (0, -128, 0x7f80) for a in vals: self.lm75_write(i2, 2, a) for b in vals: self.lm75_write(i2, 3, b) self.assertEqual(self.lm75_read(i2, 2), a) self.assertEqual(self.lm75_read(i2, 3), b) self.assertEqual(self.lm75_slow_read(i2, 2), a) self.assertEqual(self.lm75_slow_read(i2, 3), b) self.lm75_write(i2, 2, 0x4b00) self.lm75_write(i2, 3, 0x5000) self.assertEqual(self.lm75_read(i2, 2), 0x4b00) self.assertEqual(self.lm75_read(i2, 3), 0x5000) self.stacksame() def test_regrd256(self): i2 = self.i2 reg = 3 self.lm75_write(i2, reg, 0x7480) for n in (127, 128, 129): self.assertEqual(i2.regrd(0x48, reg, ">" + str(n) + "h"), (0x7480,) * n) def test_regwr(self): i2c = self.i2 sa0 = 0x48 wdata = [] lcnt = 16 for i in range(lcnt): x = random.randint(0, 255) wdata.append(x) # print(wdata) i2c.regwr(sa0, 0x00, wdata) time.sleep(0.5) x = i2c.regrd(sa0, 0x00, "<16B") # print(x) def test_setspeed(self): i2 = self.init() self.stack0() for s in (100, 400, 400, 100, 400): i2.setspeed(s) i2.getstatus() self.assertEqual(i2.speed, s) self.confirm() self.stacksame() def test_cap_idle(self): i2 = self.init() c = i2.capture_start() t0 = time.time() d = i2.ser.read(15) t1 = time.time() i2.capture_stop() self.assertEqual(d, b'\x00' * 15) self.assertTrue(0.4 < (t1 - t0) < 0.6) def test_cap_0(self): def test_0(): self.lm75_write(ag, 2, 0x4b00) return [ i2cdriver.START(0x48, 0, 1), i2cdriver.BYTE(0x02, 0, True), i2cdriver.BYTE(0x4b, 0, True), i2cdriver.BYTE(0x00, 0, True), i2cdriver.STOP() ] def test_1(): self.lm75_slow_read(ag, 2) return [ i2cdriver.START, (0x90, True), (0x02, True), i2cdriver.START, (0x91, True), (0x4b, True), (0x00, False), i2cdriver.STOP ] i2 = self.init() ag = self.ag for t in (test_0, ): # test_1): c = i2.capture_start() time.sleep(.1) ee = t() for e,a in zip(ee, c()): self.assertEqual(a, e) i2.capture_stop() def test_pullups(self): i2 = self.init() i2.getstatus() self.assertEqual(i2.pullups, 0b100100) rr = random.sample(list(range(64)), 64) if i2.product == "i2cdriver1": respins = (0, 1, 3, 13, 14, 16) else: respins = (10, 11, 12, 6, 7, 8) for r in rr: i2.setpullups(r) i2.getstatus() self.assertEqual(i2.pullups, r) s = i2.introspect() p = s["P0"] + (s["P1"] << 8) + (s["P2"] << 16) d = s["P0MDOUT"] + (s["P1MDOUT"] << 8) + (s["P2MDOUT"] << 16) for b,pb in enumerate(respins): self.assertEqual(bit(pb, p), 1) self.assertEqual(bit(b, r), bit(pb, d)) def test_zz5s(self): i2 = self.init() time.sleep(5) i2.getstatus() self.assertTrue(i2.uptime in (4,5,6)) def checkmode(self, c): self.i2.getstatus() self.assertEqual(self.i2.mode, c) def test_bitbang(self): i2 = self.init() self.checkmode('I') self.stack0() i2.ser.write(b'b') for i in range(1000): # Square wave for a while i2.ser.write(byte(0b1111) + byte(0b0101)) i2.ser.write(byte(0b1010) + byte(0b11010)) # Float, request a byte self.assertEqual(struct.unpack("B", i2.ser.read(1)), (3, )) # both should be high i2.ser.write(byte(0b0101)) # Leave driven low i2.ser.write(b'@') self.checkmode('B') i2.restore() self.checkmode('I') self.stacksame() self.assertEqual(self.lm75_read(i2, 2), 0x4b00) def test_bitbang_idem(self): # Confirm bitbang mode idempotence i2 = self.init() if i2.product != "spidriver1": return for n in [0b1101, 0b1011, 0b0000, 0b1111] + list(range(16)): i2.ser.write(b'b' + byte(n) + byte(0x40)) s1 = i2.introspect() self.assertEqual(bit(0, n), bit(2, s1["P0MDOUT"])) self.assertEqual(bit(1, n), bit(2, s1["P0"])) self.assertEqual(bit(2, n), bit(4, s1["P1MDOUT"])) self.assertEqual(bit(3, n), bit(4, s1["P1"])) i2.ser.write(b'b' + byte(0x40)) s2 = i2.introspect() for i in ("P0", "P1", "P0MDOUT", "P1MDOUT"): self.assertEqual(s1[i], s2[i]) self.assertEqual(i2.introspect()["SMB0CF"], 0x00) i2.restore() self.assertEqual(i2.introspect()["SMB0CF"], 0xd8) def test_bitbang_bidir(self): self.stack0() dd = (self.i2, self.ag) [i2.ser.write(b'b') for i2 in dd] LOW = 0b01 HIGH = 0b11 INPUT = 0b10 def port(d, sda, scl, read = False): d.ser.write(byte(sda | (scl << 2) | (int(read) << 4))) if read: (r,) = struct.unpack("B", d.ser.read(1)) return (r & 1, (r >> 1) & 1) for sda in (LOW, HIGH, LOW): for scl in (HIGH, LOW, HIGH): expected = (int(sda == HIGH), int(scl == HIGH)) for (tx,rx) in [(0,1), (1,0)]: port(dd[tx], sda, scl) port(dd[rx], INPUT, INPUT) self.assertEqual(expected, port(dd[rx], INPUT, INPUT, True)) [i2.ser.write(b'@') for i2 in dd] [i2.restore() for i2 in dd] self.stacksame() def test_reset(self): i2 = self.init() self.stack0() i2.reset() self.stacksame() for i in range(100): i2.reset() self.stacksame() self.confirm() def test_sampling(self): self.confirm_sampling() def test_weigh(self): # Confirm resistance measurement i2 = self.init() ag = self.ag self.stack0() def sample(p, pv): i2.setpullups(p) i2.ser.write(b'v' + byte(pv)) while True: i2.ser.write(b'w') r = struct.unpack("B", i2.ser.read(1)) if r[0] == 0: break return struct.unpack("2B", i2.ser.read(2)) def estimate(a, hi, res): if a == 0: return 0 v = a / hi return (res / v) - res def mean(s): return sum(s) / len(s) def resistance(rr): if rr == []: return 0 return 1 / sum([1/r for r in rr]) def pullups(): sHH = sample(0b111111, 0b111111) sAA = sample(0b001001, 0b110110) sBB = sample(0b010010, 0b101101) sCC = sample(0b100100, 0b011011) sda_r = mean((estimate(sAA[0], sHH[0], 2200), estimate(sBB[0], sHH[0], 4300), estimate(sCC[0], sHH[0], 4700))) scl_r = mean((estimate(sAA[1], sHH[1], 2200), estimate(sBB[1], sHH[1], 4300), estimate(sCC[1], sHH[1], 4700))) return (sda_r, scl_r) for x in range(64): # print(x) ag.setpullups(x) esda = resistance([r for i,r in enumerate([2200, 4300, 4700]) if bit(i, x)]) escl = resistance([r for i,r in enumerate([2200, 4300, 4700]) if bit(3 + i, x)]) # print("expected %d" % esda, escl) sda,scl = pullups() # print("SDA pullup %d, SCL pullup %d" % (sda,scl)) def close(e, a): margin = max(100, e / 10) return abs(a - e) < margin self.assertTrue(close(esda, sda)) self.assertTrue(close(escl, scl)) self.confirm_sampling() self.init() # restore pullups if __name__ == '__main__': unittest.main() ================================================ FILE: python3/.gitignore ================================================ dist/ i2cdriver.egg-info/ ================================================ FILE: python3/EDS.py ================================================ """ Drivers for electricdollarstore I2C parts """ import struct import time import datetime class Dig2: """ DIG2 is a 2-digit 7-segment LED display """ def __init__(self, i2, a = 0x14): self.i2 = i2 self.a = a def raw(self, b0, b1): """ Set all 8 segments from the bytes b0 and b1 """ self.i2.regwr(self.a, 0, struct.pack("BB", b0, b1)) def hex(self, b): """ Display a hex number 0-0xff """ self.i2.regwr(self.a, 1, b) def dec(self, b): """ Display a decimal number 00-99 """ self.i2.regwr(self.a, 2, b) def dp(self, p0, p1): """ Set the state the decimal point indicators """ self.i2.regwr(self.a, 3, (p1 << 1) | p0) def brightness(self, b): """ Set the brightness from 0 (off) to 255 (maximum) """ self.i2.regwr(self.a, 4, b) class LED: """ LED is an RGB LED """ def __init__(self, i2, a = 0x08): self.i2 = i2 self.a = a def rgb(self, r, g, b, t = 0): """ Set the color to (r,g,b). Each is a byte 0-255. If t is nonzero, the change happens over t/30 seconds. For example if t is 15 the color fades over a half-second. """ if t == 0: self.i2.start(self.a, 0) self.i2.regwr(self.a, 0, bytes([r, g, b])) else: self.i2.start(self.a, 0) self.i2.regwr(self.a, 1, bytes([r, g, b, t])) def hex(self, hhh, t = 0): """ Set the color to hhh, a 24-bit RGB color. If t is nonzero, the change happens over t/30 seconds. For example if t is 15 the color fades over a half-second. """ r = (hhh >> 16) & 0xff g = (hhh >> 8) & 0xff b = hhh & 0xff self.rgb(r, g, b, t) class Pot: """ POT is an analog knob potentiometer """ def __init__(self, i2, a = 0x28): self.i2 = i2 self.a = a def raw(self): """ Return the current knob rotation as a 16-bit integer. """ return self.i2.regrd(self.a, 0, "H") def rd(self, r): """ Return the current knob rotation, scaled to the range 0 .. r inclusive. For example rd(100) returns a value in the range 0 to 100. """ return self.i2.regrd(self.a, r) class Beep: """ BEEP is a beeper """ def __init__(self, i2, a = 0x30): self.i2 = i2 self.a = a def beep(self, dur, note): """ Play a note. dur is the duration in milliseconds, 0-255. note is a MIDI note in the range 21-127 inclusive. """ self.i2.regwr(self.a, dur, note) class Remote: """ REMOTE is a NEC IR code receiver / decoder """ def __init__(self, i2, a = 0x60): self.i2 = i2 self.a = a def key(self): """ For the electricdollarstore IR transmitter. If there is a code in the queue, return its character code. The layout of the remote is p c n < > ' ' - + = 0 % & 1 2 3 4 5 6 7 8 9 If there is no IR code in the queue, return None. """ r = self.i2.regrd(self.a, 0) if r != 0: return chr(r) def raw(self): """ If there is a code in the queue, return a tuple containing the four-byte code, and a timestamp. If there is no IR code in the queue, return None. """ r = self.i2.regrd(self.a, 1, "4BH") if r[:4] != (0xff, 0xff, 0xff, 0xff): age_in_ms = r[4] return (r[:4], time.time() - age_in_ms * .001) else: return None class Temp: """ TEMP is a LM75B temperature sesnor """ def __init__(self, i2, a = 0x48): self.i2 = i2 self.a = a def reg(self, r): return self.i2.regrd(self.a, r, ">h") def read(self): """ Return the current temperature in Celsius """ return (self.reg(0) >> 5) * 0.125 class EPROM: """ EPROM is a CAT24C512 512 Kbit (64 Kbyte) flash memory """ def __init__(self, i2, a = 0x50): self.i2 = i2 self.a = a def write(self, addr, data): """ Write data to EPROM, starting at address addr """ for i in range(0, len(data), 128): self.i2.start(self.a, 0) self.i2.write(struct.pack(">H", addr + i)) self.i2.write(data[i:i + 128]) self.i2.stop() while self.i2.start(self.a, 0) == False: pass def read(self, addr, n): """ Read n bytes from the EPROM, starting at address addr """ self.i2.start(self.a, 0) self.i2.write(struct.pack(">H", addr)) self.i2.start(self.a, 1) r = self.i2.read(n) self.i2.stop() return r self.i2.stop() class Clock: """ CLOCK is a HT1382 I2C/3-Wire Real Time Clock with a 32 kHz crystal """ def __init__(self, i2, a = 0x68): self.i2 = i2 self.a = a def set(self, t = None): if t is None: t = datetime.datetime.now() def bcd(x): return (x % 10) + 16 * (x // 10) self.i2.regwr(self.a, 7, 0) self.i2.regwr(self.a, 6, bcd(t.year % 100)) self.i2.regwr(self.a, 5, 1 + t.weekday()) self.i2.regwr(self.a, 4, bcd(t.month)) self.i2.regwr(self.a, 3, bcd(t.day)) self.i2.regwr(self.a, 2, 0x80 | bcd(t.hour)) # use 24-hour mode self.i2.regwr(self.a, 1, bcd(t.minute)) self.i2.regwr(self.a, 0, bcd(t.second)) def read(self): self.i2.start(self.a, 0) self.i2.write([0]) self.i2.stop() self.i2.start(self.a, 1) (ss,mm,hh,dd,MM,ww,yy) = (struct.unpack("7B", self.i2.read(7))) self.i2.stop() def dec(x): return (x % 16) + 10 * (x // 16) return datetime.datetime( 2000 + dec(yy), dec(MM), dec(dd), dec(hh & 0x7f), dec(mm), dec(ss)) def dump(self): self.i2.start(self.a, 0) self.i2.write([0]) self.i2.stop() self.i2.start(self.a, 1) print(list(self.i2.read(16))) self.i2.stop() class Magnet: """ MAGNET is an ST LIS3MDL 3-axis magnetometer """ def __init__(self, i2, a = 0x1c): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x22, 0) # CTRL_REG3 operating mode 0: continuous conversion def rd(self): """ Read the measurement STATUS_REG and OUT_X,Y,Z """ return self.i2.regrd(self.a, 0x27, "" % (self.addr, self.rrw(), self.rack()) def dump(self, f, fmt): if fmt == "csv": f.writerow(("START", self.rrw(), str(self.addr), self.rack())) else: assert False, "unsupported format" def __eq__(self, other): return (self.addr, self.rw, self.ack) == (other.addr, other.rw, other.ack) class STOP(_I2CEvent): def __repr__(self): return "" def dump(self, f, fmt): if fmt == "csv": f.writerow(("STOP", None, None, None)) else: assert False, "unsupported format" def __eq__(self, other): return isinstance(other, STOP) class BYTE(_I2CEvent): def __init__(self, b, rw, ack): self.b = b self.rw = rw self.ack = ack def __repr__(self): return "<%s 0x%02x %s>" % (self.rrw(), self.b, self.rack()) def dump(self, f, fmt): if fmt == "csv": f.writerow(("BYTE", self.rrw(), str(self.b), self.rack())) else: assert False, "unsupported format" def __eq__(self, other): return (self.b, self.rw, self.ack) == (other.b, other.rw, other.ack) class I2CDriver: """ A connected I2CDriver. :param port: The USB port to connect to :type port: str :param reset: Issue an I2C bus reset on connection :type reset: bool After connection, the following object variables reflect the current values of the I2CDriver. They are updated by calling :py:meth:`getstatus`. :ivar product: product code e.g. 'i2cdriver1' or 'i2cdriverm' :ivar serial: serial string of I2CDriver :ivar uptime: time since I2CDriver boot, in seconds :ivar voltage: USB voltage, in V :ivar current: current used by attached device, in mA :ivar temp: temperature, in degrees C :ivar scl: state of SCL :ivar sda: state of SDA :ivar speed: current device speed in KHz (100 or 400) :ivar mode: IO mode (I2C or bitbang) :ivar pullups: programmable pullup enable pins :ivar ccitt_crc: CCITT-16 CRC of all transmitted and received bytes """ def __init__(self, port = "/dev/ttyUSB0", reset = True): """ Connect to a hardware i2cdriver. :param port: The USB port to connect to :type port: str :param reset: Issue an I2C bus reset on connection :type reset: bool """ self.ser = serial.Serial(port, 1000000, timeout = 1) # May be in capture or monitor mode, send char and wait for 50 ms self.ser.write(b'@') time.sleep(.050) # May be waiting up to 64 bytes of input (command code 0xff) self.ser.write(b'@' * 64) self.ser.flush() while self.ser.inWaiting(): self.ser.read(self.ser.inWaiting()) for c in [0x55, 0x00, 0xff, 0xaa]: r = self.__echo(c) if r != c: print('Echo test failed - not attached?') print('Expected %r but received %r' % (c, r)) raise IOError self.getstatus() if reset == "never": return if reset or (self.scl, self.sda) != (1, 1): if self.reset() != 3: raise I2CTimeout("Bus failed to reset - check connected devices") self.getstatus() self.setspeed(100) if PYTHON2: def __ser_w(self, s): if isinstance(s, list) or isinstance(s, tuple): s = "".join([chr(c) for c in s]) self.ser.write(s) else: def __ser_w(self, s): if isinstance(s, list) or isinstance(s, tuple): s = bytes(s) self.ser.write(s) def __echo(self, c): self.__ser_w([ord('e'), c]) r = self.ser.read(1) if PYTHON2: return ord(r[0]) else: return r[0] def setspeed(self, s): """ Set the I2C bus speed. :param s: speed in KHz, either 100 or 400 :type s: int """ assert s in (100, 400) c = {100:b'1', 400:b'4'}[s] self.__ser_w(c) self.speed = s def setpullups(self, s): """ Set the I2CDriver pullup resistors :param s: 6-bit pullup mask """ assert 0 <= s < 64 self.__ser_w([ord('u'), s]) self.pullups = s def scan(self, silent = False): """ Performs an I2C bus scan. If silent is False, prints a map of devices. Returns a list of the device addresses. >>> i2c.scan() -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1C -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- [28, 72, 104] """ self.ser.write(b'd') d = struct.unpack("112c", self.ser.read(112)) if not silent: for a,p in enumerate(d, 8): if p == b"1": st = "%02X" % a else: st = "--" sys.stdout.write(st + " ") if (a % 8) == 7: sys.stdout.write("\n") return [a for a,p in enumerate(d, 8) if p == b"1"] def reset(self): """ Send an I2C bus reset """ self.__ser_w(b'x') return struct.unpack("B", self.ser.read(1))[0] & 3 def start(self, dev, rw): """ Start an I2C transaction :param dev: 7-bit I2C device address :param rw: read (1) or write (0) To write bytes ``[0x12,0x34]`` to device ``0x75``: >>> i2c.start(0x75, 0) >>> i2c.write([0x12,034]) >>> i2c.stop() """ self.__ser_w([ord('s'), (dev << 1) | rw]) return self.ack() def ack(self): a = ord(self.ser.read(1)) if a & 2: raise I2CTimeout return (a & 1) != 0 def read(self, l): """ Read l bytes from the I2C device, and NAK the last byte """ r = [] if l >= 64: bulkpart = (l-1) // 64 for i in range(bulkpart): self.__ser_w([ord('a'), 64]) r.append(self.ser.read(64)) l -= 64 * bulkpart assert 0 <= l <= 64 self.__ser_w([0x80 + l - 1]) r.append(self.ser.read(l)) return b''.join(r) def write(self, bb): """ Write bytes to the selected I2C device :param bb: sequence to write """ ack = True for i in range(0, len(bb), 64): sub = bb[i:i + 64] self.__ser_w([0xc0 + len(sub) - 1]) self.__ser_w(sub) ack = self.ack() return ack def stop(self): """ stop the i2c transaction """ self.ser.write(b'p') def reboot(self): self.__ser_w(b'_') time.sleep(.5) def regrd(self, dev, reg, fmt = "B"): """ Read a register from a device. :param dev: 7-bit I2C device address :param reg: register address 0-255 :param fmt: :py:func:`struct.unpack` format string for the register contents, or an integer byte count If device 0x75 has a 16-bit unsigned big-endian register 102, it can be read with: >>> i2c.regrd(0x75, 102, ">H") 4999 """ if isinstance(fmt, str): r = struct.unpack(fmt, self.regrd(dev, reg, struct.calcsize(fmt))) if len(r) == 1: return r[0] else: return r else: n = fmt if n <= 256: self.__ser_w(b'r' + struct.pack("BBB", dev, reg, n & 0xff)) return self.ser.read(n) else: self.start(dev, 0) self.write([reg]) self.start(dev, 1) r = self.read(n) self.stop() return r def regwr(self, dev, reg, vv): """Write a device's register. :param dev: 7-bit I2C device address :param reg: register address 0-255 :param vv: value to write. Either a single byte, or a sequence To set device 0x34 byte register 7 to 0xA1: >>> i2c.regwr(0x34, 7, 0xa1) If device 0x75 has a big-endian 16-bit register 102 you can set it to 4999 with: >>> i2c.regwr(0x75, 102, struct.pack(">H", 4999)) """ r = self.start(dev, 0) if r: r = self.write(struct.pack("B", reg)) if r: if isinstance(vv, int): vv = struct.pack("B", vv) r = self.write(vv) self.stop() return r def monitor(self, s): """ Enter or leave monitor mode :param s: ``True`` to enter monitor mode, ``False`` to leave """ if s: self.__ser_w(b'm') time.sleep(.1) else: self.__ser_w(b' ') time.sleep(.1) self.__echo(0x40) def introspect(self): self.ser.write(b'J') r = self.ser.read(80) assert len(r) == 80, r body = r[1:-1].decode() # remove [ and ] nn = ( "id ds sp SMB0CF SMB0CN T2 T3 IE EIE1 P0 P0MDIN P0MDOUT P1 P1MDIN P1MDOUT P2 P2MDOUT".split() + "convs".split() ) bb = [int(w, 16) for w in body.split()] assert len(nn) == len(bb) return InternalState(zip(nn, bb)) def restore(self): self.ser.write(b'i') def __repr__(self): return "<%s serial=%s uptime=%d, SCL=%d, SDA=%d>" % ( self.product, self.serial, self.uptime, self.scl, self.sda) def capture_start(self, idle=False, start = START, abyte = BYTE, stop = STOP): """Enter I2C capture mode, capturing I2C transactions. :param idle: If ``True`` the generator returns ``None`` when the bus is idle. If ``False`` the generator does nothing during bus idle. :return: a generator which returns an object for each I2C primitive captured. """ self.__ser_w([ord('c')]) def nstream(): while True: bb = self.ser.read(256) if PYTHON2: for b in bb: yield (ord(b) >> 4) & 0xf yield ord(b) & 0xf else: for b in bb: yield (b >> 4) & 0xf yield b & 0xf def parser(): starting = False rw = 0 for n in nstream(): if n == 0: if idle: yield None elif n == 1: starting = True bits = [] elif n == 2: yield stop() starting = True bits = [] elif n in (8,9,10,11,12,13,14,15): # w(str(n&7)) bits.append(n & 7) if len(bits) == 3: b9 = (bits[0] << 6) | (bits[1] << 3) | bits[2] b8 = (b9 >> 1) ack = b9 & 1 if starting: rw = b8 & 1 yield start(b8 >> 1, rw, ack == 0) starting = False else: yield abyte(b8, rw, ack == 0) bits = [] else: assert 0, "unexpected token" return parser def capture_stop(self): while self.ser.in_waiting: self.ser.read(self.ser.in_waiting) self.__ser_w([ord('c')]) while self.ser.in_waiting: self.ser.read(self.ser.in_waiting) self.__echo(0x40) def capture(self): self.__ser_w([ord('c')]) while 0: b = self.ser.read(1) for c in b: print("%02x" % c) w = sys.stdout.write def nstream(): while 1: for b in self.ser.read(256): yield (b >> 4) & 0xf yield b & 0xf bits = [] for n in nstream(): if n == 0: w(".") elif n == 1: w("S") bits = [] elif n == 2: w("P\n") bits = [] elif n in (8,9,10,11,12,13,14,15): # w(str(n&7)) bits.append(n & 7) if len(bits) == 3: b9 = (bits[0] << 6) | (bits[1] << 3) | bits[2] b8 = (b9 >> 1) ack = b9 & 1 w('%02x%s' % (b8, " !"[ack])) bits = [] else: assert 0, "unexpected token" def getstatus(self): """ Update all status variables """ self.ser.write(b'?') r = self.ser.read(80) body = r[1:-1].decode() # remove [ and ] (self.product, self.serial, uptime, voltage, current, temp, mode, sda, scl, speed, pullups, ccitt_crc) = body.split() self.uptime = int(uptime) self.voltage = float(voltage) self.current = float(current) self.temp = float(temp) self.mode = mode self.scl = int(scl) self.sda = int(sda) self.speed = int(speed) self.pullups = int(pullups, 16) self.ccitt_crc = int(ccitt_crc, 16) return repr(self) ================================================ FILE: python3/pyproject.toml ================================================ [build-system] requires = ["setuptools>=61"] build-backend = "setuptools.build_meta" [project] name = "i2cdriver" version = "1.0.6" description = "I2CDriver is a desktop I2C interface" readme = "README.md" # optional, use if you want the long description from a file authors = [ { name = "James Bowman", email = "jamesb@excamera.com" } ] license = "BSD-3-Clause" dependencies = ["pyserial"] [project.urls] Homepage = "http://i2cdriver.com" Documentation = "https://i2cdriver.readthedocs.io/en/latest/" [project.scripts] i2cgui = "samples.i2cgui:main" [tool.setuptools] py-modules = ["i2cdriver", "EDS"] ================================================ FILE: python3/samples/EDS-ACCEL.py ================================================ import sys import struct import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.scan() d = EDS.Accel(i2) while True: print("x=%+.3f y=%+.3f z=%+.3f" % d.measurement()) ================================================ FILE: python3/samples/EDS-BEEP.py ================================================ import sys import serial import time import struct import random from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1], True) d = EDS.Beep(i2) for note in range(55, 127): print("MIDI note %d" % note) d.beep(100, note) time.sleep(.100) ================================================ FILE: python3/samples/EDS-CLOCK.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Clock(i2) d.set() while 1: print(d.read()) time.sleep(1) ================================================ FILE: python3/samples/EDS-DIG2.py ================================================ import sys import serial import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Dig2(i2) for i in range(100): d.dec(i) time.sleep(.05) ================================================ FILE: python3/samples/EDS-EPROM.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS text = b"""\ CHAPTER 1. Loomings. Call me Ishmael. Some years ago-never mind how long precisely-having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people's hats off-then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me. There now is your insular city of the Manhattoes, belted round by wharves as Indian isles by coral reefs-commerce surrounds it with her surf. Right and left, the streets take you waterward. Its extreme downtown is the battery, where that noble mole is washed by waves, and cooled by breezes, which a few hours previous were out of sight of land. Look at the crowds of water-gazers there. Circumambulate the city of a dreamy Sabbath afternoon. Go from Corlears Hook to Coenties Slip, and from thence, by Whitehall, northward. What do you see?-Posted like silent sentinels all around the town, stand thousands upon thousands of mortal men fixed in ocean reveries. Some leaning against the spiles; some seated upon the pier-heads; some looking over the bulwarks of ships from China; some high aloft in the rigging, as if striving to get a still better seaward peep. But these are all landsmen; of week days pent up in lath and plaster-tied to counters, nailed to benches, clinched to desks. How then is this? Are the green fields gone? What do they here? But look! here come more crowds, pacing straight for the water, and seemingly bound for a dive. Strange! Nothing will content them but the extremest limit of the land; loitering under the shady lee of yonder warehouses will not suffice. No. They must get just as nigh the water as they possibly can without falling in. And there they stand-miles of them-leagues. Inlanders all, they come from lanes and alleys, streets and avenues-north, east, south, and west. Yet here they all unite. Tell me, does the magnetic virtue of the needles of the compasses of all those ships attract them thither? Once more. Say you are in the country; in some high land of lakes. Take almost any path you please, and ten to one it carries you down in a dale, and leaves you there by a pool in the stream. There is magic in it. Let the most absent-minded of men be plunged in his deepest reveries-stand that man on his legs, set his feet a-going, and he will infallibly lead you to water, if water there be in all that region. Should you ever be athirst in the great American desert, try this experiment, if your caravan happen to be supplied with a metaphysical professor. Yes, as every one knows, meditation and water are wedded for ever. """ if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.EPROM(i2) d.write(0, text) # Write the block of text starting at address 0 n = len(text) rd = d.read(0, n) # Read it back print(rd.decode()) # Display it ================================================ FILE: python3/samples/EDS-LED.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.LED(i2) TEAL = 0x008080 ORANGE = 0xffa500 while 1: time.sleep(1) d.hex(TEAL, 3) time.sleep(1) d.hex(ORANGE, 3) ================================================ FILE: python3/samples/EDS-MAGNET.py ================================================ import sys import struct import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Magnet(i2) while 1: print(d.measurement()) ================================================ FILE: python3/samples/EDS-POT.py ================================================ import sys import struct import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Pot(i2) while 1: percentage = d.rd(100) r = d.raw() print("%3d/100 raw=%3d" % (percentage, r)) time.sleep(.05) ================================================ FILE: python3/samples/EDS-REMOTE.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1], True) i2.setspeed(400) d = EDS.Remote(i2) print("Press a remote button") while 1: k = d.key() if k is not None: print("Key : %r" % k) r = d.raw() if r is not None: (code, timestamp) = r print("Raw code: %02x %02x %02x %02x (time %.2f)" % (code[0], code[1], code[2], code[3], timestamp)) time.sleep(.25) ================================================ FILE: python3/samples/EDS-TEMP.py ================================================ import sys import time from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = EDS.Temp(i2) for i in range(20): celsius = d.read() fahrenheit = celsius * 9/5 + 32 sys.stdout.write("%.1f C %.1f F\n" % (celsius, fahrenheit)) time.sleep(.1) ================================================ FILE: python3/samples/EDS-color-compass.py ================================================ """ Demo of a simple combination of parts from Electric Dollar Store: * MAGNET - 3-axis magnetometer * LED - RGB LED This demo takes the compass direction, and uses it to set the LED's color. So as you move the module around, the color changes according to its direction. There is a direction that is pure red, another that is pure green, etc. https://electricdollarstore.com """ import sys from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) magnet = EDS.Magnet(i2) led = EDS.LED(i2) while True: (x, y, z) = magnet.measurement() r = max(0, min(255, (x + 4000) // 32)) g = max(0, min(255, (y + 4000) // 32)) b = max(0, min(255, (z + 4000) // 32)) led.rgb(r, g, b) ================================================ FILE: python3/samples/EDS-egg-timer.py ================================================ """ Demo of a simple combination of parts from Electric Dollar Store: * POT - potentiometer * DIG2 - 2-digit display * BEEP - piezo beeper This demo simulates a kitchen egg-timer. Twisting the POT sets a countdown time in seconds, and after it's released the ticker starts counting. When it reaches "00" it flashes and beeps. https://electricdollarstore.com """ import sys import time from i2cdriver import I2CDriver, EDS def millis(): return int(time.time() * 1000) def eggtimer(i2c): pot = EDS.Pot(i2c) beep = EDS.Beep(i2c) digits = EDS.Dig2(i2c) ticking = False v0 = pot.rd(99) next = millis() + 4000 digits.brightness(50) t = 0 while True: v = pot.rd(99) if v0 != v: if v0 < v: beep.beep(2, 80) else: beep.beep(1, 117) ticking = False next = millis() + 1000 v0 = v digits.brightness(255) t = v digits.dec(t) if millis() > next and (t != 0): ticking = True if ticking and millis() > next: next = millis() + 1000 beep.beep(1, 120) if t: t -= 1 else: for i in range(21): digits.brightness(255) beep.beep(75, 107) time.sleep(.1) digits.brightness(0) time.sleep(.05) digits.brightness(50) ticking = False if __name__ == '__main__': i2 = I2CDriver(sys.argv[1], True) eggtimer(i2) ================================================ FILE: python3/samples/EDS-take-a-ticket.py ================================================ """ Demo of a simple combination of parts from Electric Dollar Store: * REMOTE - remote control receiver * DIG2 - 2-digit display * BEEP - piezo beeper This demo runs a take-a-ticket display for a store or deli counter. It shows 2-digit "now serving" number, and each time '+' is pressed on the remote it increments the counter and makes a beep, so the next customer can be served. Pressing '-' turns the number back one. https://electricdollarstore.com """ import sys from i2cdriver import I2CDriver, EDS if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) remote = EDS.Remote(i2) beep = EDS.Beep(i2) dig2 = EDS.Dig2(i2) counter = 0 while True: k = remote.key() if k == '+': beep.beep(255, 90) counter = (counter + 1) % 100 if k == '-': beep.beep(100, 80) counter = (counter - 1) % 100 dig2.dec(counter) ================================================ FILE: python3/samples/bargraph.py ================================================ """ Example for Bi-Color (Red/Green) 24-Bar Bargraph, based on HT16K33. Available from Adafruit. """ import sys import time import random from i2cdriver import I2CDriver from ht16k33 import HT16K33 class bargraph(HT16K33): def set(self, pix): rr = pix def paint(r, i): """ Paint pixel i """ blk = i // 12 i %= 12 b = i // 4 m = 1 << ((i % 4) + 4 * blk) r[b] |= m red = [0,0,0] grn = [0,0,0] [paint(red, i) for i in range(24) if (pix[i] & 1)] [paint(grn, i) for i in range(24) if (pix[i] & 2)] self.load([red[0], grn[0], red[1], grn[1], red[2], grn[2]]) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d0 = bargraph(i2) for i in range(60): d0.set([random.choice((0,1,2,3)) for i in range(24)]) time.sleep(.08) ================================================ FILE: python3/samples/bmp390.py ================================================ # SPDX-FileCopyrightText: 2018 Carter Nelson for Adafruit Industries # # SPDX-License-Identifier: MIT """ `adafruit_bmp3xx` ==================================================== CircuitPython driver from BMP388 Temperature and Barometric Pressure sensor. * Author(s): Carter Nelson Implementation Notes -------------------- **Hardware:** * `Adafruit BMP388 - Precision Barometric Pressure and Altimeter `_ (Product ID: 3966) **Software and Dependencies:** * Adafruit CircuitPython firmware for the supported boards: https://circuitpython.org/downloads * Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice """ import struct import time # from micropython import const def const(x): return x __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_BMP3XX.git" _BMP388_CHIP_ID = const(0x50) _BMP390_CHIP_ID = const(0x60) # pylint: disable=import-outside-toplevel _REGISTER_CHIPID = const(0x00) _REGISTER_STATUS = const(0x03) _REGISTER_PRESSUREDATA = const(0x04) _REGISTER_TEMPDATA = const(0x07) _REGISTER_CONTROL = const(0x1B) _REGISTER_OSR = const(0x1C) _REGISTER_ODR = const(0x1D) _REGISTER_CONFIG = const(0x1F) _REGISTER_CAL_DATA = const(0x31) _REGISTER_CMD = const(0x7E) _OSR_SETTINGS = (1, 2, 4, 8, 16, 32) # pressure and temperature oversampling settings _IIR_SETTINGS = (0, 2, 4, 8, 16, 32, 64, 128) # IIR filter coefficients class BMP3XX: """Base class for BMP3XX sensor.""" def __init__(self): chip_id = self._read_byte(_REGISTER_CHIPID) if chip_id not in (_BMP388_CHIP_ID, _BMP390_CHIP_ID): raise RuntimeError("Failed to find BMP3XX! Chip ID 0x%x" % chip_id) self._read_coefficients() self.reset() self.sea_level_pressure = 1013.25 self._wait_time = 0.002 # change this value to have faster reads if needed """Sea level pressure in hPa.""" @property def pressure(self): """The pressure in hPa.""" return self._read()[0] / 100 @property def temperature(self): """The temperature in degrees Celsius""" return self._read()[1] @property def altitude(self): """The altitude in meters based on the currently set sea level pressure.""" # see https://www.weather.gov/media/epz/wxcalc/pressureAltitude.pdf return 44307.7 * (1 - (self.pressure / self.sea_level_pressure) ** 0.190284) @property def pressure_oversampling(self): """The pressure oversampling setting.""" return _OSR_SETTINGS[self._read_byte(_REGISTER_OSR) & 0x07] @pressure_oversampling.setter def pressure_oversampling(self, oversample): if oversample not in _OSR_SETTINGS: raise ValueError("Oversampling must be one of: {}".format(_OSR_SETTINGS)) new_setting = self._read_byte(_REGISTER_OSR) & 0xF8 | _OSR_SETTINGS.index( oversample ) self._write_register_byte(_REGISTER_OSR, new_setting) @property def temperature_oversampling(self): """The temperature oversampling setting.""" return _OSR_SETTINGS[self._read_byte(_REGISTER_OSR) >> 3 & 0x07] @temperature_oversampling.setter def temperature_oversampling(self, oversample): if oversample not in _OSR_SETTINGS: raise ValueError("Oversampling must be one of: {}".format(_OSR_SETTINGS)) new_setting = ( self._read_byte(_REGISTER_OSR) & 0xC7 | _OSR_SETTINGS.index(oversample) << 3 ) self._write_register_byte(_REGISTER_OSR, new_setting) @property def filter_coefficient(self): """The IIR filter coefficient.""" return _IIR_SETTINGS[self._read_byte(_REGISTER_CONFIG) >> 1 & 0x07] @filter_coefficient.setter def filter_coefficient(self, coef): if coef not in _IIR_SETTINGS: raise ValueError( "Filter coefficient must be one of: {}".format(_IIR_SETTINGS) ) self._write_register_byte(_REGISTER_CONFIG, _IIR_SETTINGS.index(coef) << 1) def reset(self): """Perform a power on reset. All user configuration settings are overwritten with their default state. """ self._write_register_byte(_REGISTER_CMD, 0xB6) def _read(self): """Returns a tuple for temperature and pressure.""" # OK, pylint. This one is all kinds of stuff you shouldn't worry about. # pylint: disable=invalid-name, too-many-locals # Perform one measurement in forced mode self._write_register_byte(_REGISTER_CONTROL, 0x13) # Wait for *both* conversions to complete while self._read_byte(_REGISTER_STATUS) & 0x60 != 0x60: time.sleep(self._wait_time) # Get ADC values data = self._read_register(_REGISTER_PRESSUREDATA, 6) adc_p = data[2] << 16 | data[1] << 8 | data[0] adc_t = data[5] << 16 | data[4] << 8 | data[3] # datasheet, sec 9.2 Temperature compensation T1, T2, T3 = self._temp_calib pd1 = adc_t - T1 pd2 = pd1 * T2 temperature = pd2 + (pd1 * pd1) * T3 # datasheet, sec 9.3 Pressure compensation P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11 = self._pressure_calib pd1 = P6 * temperature pd2 = P7 * temperature ** 2.0 pd3 = P8 * temperature ** 3.0 po1 = P5 + pd1 + pd2 + pd3 pd1 = P2 * temperature pd2 = P3 * temperature ** 2.0 pd3 = P4 * temperature ** 3.0 po2 = adc_p * (P1 + pd1 + pd2 + pd3) pd1 = adc_p ** 2.0 pd2 = P9 + P10 * temperature pd3 = pd1 * pd2 pd4 = pd3 + P11 * adc_p ** 3.0 pressure = po1 + po2 + pd4 # pressure in hPa, temperature in deg C return pressure, temperature def _read_coefficients(self): """Read & save the calibration coefficients""" coeff = self._read_register(_REGISTER_CAL_DATA, 21) # See datasheet, pg. 27, table 22 coeff = struct.unpack(" self._temp_calib = ( coeff[0] / 2 ** -8.0, # T1 coeff[1] / 2 ** 30.0, # T2 coeff[2] / 2 ** 48.0, ) # T3 self._pressure_calib = ( (coeff[3] - 2 ** 14.0) / 2 ** 20.0, # P1 (coeff[4] - 2 ** 14.0) / 2 ** 29.0, # P2 coeff[5] / 2 ** 32.0, # P3 coeff[6] / 2 ** 37.0, # P4 coeff[7] / 2 ** -3.0, # P5 coeff[8] / 2 ** 6.0, # P6 coeff[9] / 2 ** 8.0, # P7 coeff[10] / 2 ** 15.0, # P8 coeff[11] / 2 ** 48.0, # P9 coeff[12] / 2 ** 48.0, # P10 coeff[13] / 2 ** 65.0, ) # P11 def _read_byte(self, register): """Read a byte register value and return it""" return self._read_register(register, 1)[0] def _read_register(self, register, length): """Low level register reading, not implemented in base class""" raise NotImplementedError() def _write_register_byte(self, register, value): """Low level register writing, not implemented in base class""" raise NotImplementedError() class BMP3XX_I2C(BMP3XX): """Driver for I2C connected BMP3XX. :param ~busio.I2C i2c: The I2C bus the BMP388 is connected to. :param int address: I2C device address. Defaults to :const:`0x77`. but another address can be passed in as an argument **Quickstart: Importing and using the BMP388** Here is an example of using the :class:`BMP3XX_I2C` class. First you will need to import the libraries to use the sensor .. code-block:: python import board import adafruit_bmp3xx Once this is done you can define your `board.I2C` object and define your sensor object .. code-block:: python i2c = board.I2C() # uses board.SCL and board.SDA bmp = adafruit_bmp3xx.BMP3XX_I2C(i2c) Now you have access to the :attr:`temperature` and :attr:`pressure` attributes .. code-block:: python temperature = bmp.temperature pressure = bmp.pressure """ def __init__(self, i2c, address=0x77): from adafruit_bus_device import i2c_device self._i2c = i2c_device.I2CDevice(i2c, address) super().__init__() def _read_register(self, register, length): """Low level register reading over I2C, returns a list of values""" result = bytearray(length) with self._i2c as i2c: i2c.write(bytes([register & 0xFF])) i2c.readinto(result) return result def _write_register_byte(self, register, value): """Low level register writing over I2C, writes one 8-bit value""" with self._i2c as i2c: i2c.write(bytes((register & 0xFF, value & 0xFF))) class BMP3XX_SPI(BMP3XX): """Driver for SPI connected BMP3XX. :param ~busio.SPI spi: SPI device :param ~digitalio.DigitalInOut cs: Chip Select **Quickstart: Importing and using the BMP388** Here is an example of using the :class:`BMP3XX_SPI` class. First you will need to import the libraries to use the sensor .. code-block:: python import board import adafruit_bmp3xx from digitalio import DigitalInOut, Direction Once this is done you can define your `board.SPI` object and define your sensor object .. code-block:: python spi = board.SPI() cs = DigitalInOut(board.D5) bmp = adafruit_bmp3xx.BMP3XX_SPI(spi, cs) Now you have access to the :attr:`temperature` and :attr:`pressure` attributes .. code-block:: python temperature = bmp.temperature pressure = bmp.pressure """ def __init__(self, spi, cs): from adafruit_bus_device import spi_device self._spi = spi_device.SPIDevice(spi, cs) # toggle CS low/high to put BMP3XX in SPI mode with self._spi: time.sleep(0.001) super().__init__() def _read_register(self, register, length): """Low level register reading over SPI, returns a list of values""" result = bytearray(length) with self._spi as spi: # pylint: disable=no-member spi.write(bytes((0x80 | register, 0x00))) spi.readinto(result) return result def _write_register_byte(self, register, value): """Low level register writing over SPI, writes one 8-bit value""" with self._spi as spi: # pylint: disable=no-member spi.write(bytes((register & 0x7F, value & 0xFF))) # from i2cdriver import I2CDriver import sys class BMP3XX_I2CDriver(BMP3XX): """Driver for I2CDriver connected BMP3XX. :param ~busio.I2C i2c: The I2CDriver the BMP388 is connected to. :param int address: I2C device address. Defaults to :const:`0x77`. but another address can be passed in as an argument **Quickstart: Importing and using the BMP388** Here is an example of using the :class:`BMP3XX_I2CDriver` class. First you will need to import the libraries .. code-block:: python from i2cdriver import I2CDriver import adafruit_bmp3xx Once this is done you can connect to the I2CDriver and define the sensor object, e.g. .. code-block:: python i2c = I2CDriver("COM9") bmp = adafruit_bmp3xx.BMP3XX_I2C(i2c) Now you have access to the :attr:`temperature` and :attr:`pressure` attributes .. code-block:: python temperature = bmp.temperature pressure = bmp.pressure """ def __init__(self, i2c, address=0x77): self.i2c = i2c self.a = address super().__init__() def _read_register(self, register, length): """Low level register reading over I2C, returns a list of values""" return self.i2c.regrd(self.a, register, length) def _write_register_byte(self, register, value): """Low level register writing over I2C, writes one 8-bit value""" self.i2c.regwr(self.a, register, value) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = BMP3XX_I2CDriver(i2) d.pressure_oversampling = 32 d.temperature_oversampling = 32 while 1: (pressure, temperature) = d._read() print(f"Pressure: {pressure / 100:.2f} hPa") print(f"Temperature: {temperature:.2f} C") ================================================ FILE: python3/samples/bno080.py ================================================ """ Example for BNO080 integrated IMU. Available from Sparkfun. """ import sys import serial import time import struct import random import math from i2cdriver import I2CDriver def hexdump(s): def toprint(c): if 32 <= c < 127: return chr(c) else: return "." def hexline(s): return (" ".join(["%02x" % c for c in s]).ljust(49) + "|" + "".join([toprint(c) for c in s]).ljust(16) + "|") return "\n".join([hexline(s[i:i+16]) for i in range(0, len(s), 16)]) CHANNEL_COMMAND = 0 CHANNEL_EXECUTABLE = 1 CHANNEL_CONTROL = 2 CHANNEL_REPORTS = 3 CHANNEL_WAKE_REPORTS = 4 CHANNEL_GYRO = 5 # All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual # These are used for low level communication with the sensor, on channel 2 SHTP_REPORT_COMMAND_RESPONSE = 0xF1 SHTP_REPORT_COMMAND_REQUEST = 0xF2 SHTP_REPORT_FRS_READ_RESPONSE = 0xF3 SHTP_REPORT_FRS_READ_REQUEST = 0xF4 SHTP_REPORT_PRODUCT_ID_RESPONSE = 0xF8 SHTP_REPORT_PRODUCT_ID_REQUEST = 0xF9 SHTP_REPORT_BASE_TIMESTAMP = 0xFB SHTP_REPORT_SET_FEATURE_COMMAND = 0xFD # All the different sensors and features we can get reports from # These are used when enabling a given sensor SENSOR_REPORTID_ACCELEROMETER = 0x01 SENSOR_REPORTID_GYROSCOPE = 0x02 SENSOR_REPORTID_MAGNETIC_FIELD = 0x03 SENSOR_REPORTID_LINEAR_ACCELERATION = 0x04 SENSOR_REPORTID_ROTATION_VECTOR = 0x05 SENSOR_REPORTID_GRAVITY = 0x06 SENSOR_REPORTID_GAME_ROTATION_VECTOR = 0x08 SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR = 0x09 SENSOR_REPORTID_TAP_DETECTOR = 0x10 SENSOR_REPORTID_STEP_COUNTER = 0x11 SENSOR_REPORTID_STABILITY_CLASSIFIER = 0x13 SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER = 0x1E # Record IDs from figure 29, page 29 reference manual # These are used to read the metadata for each sensor type FRS_RECORDID_ACCELEROMETER = 0xE302 FRS_RECORDID_GYROSCOPE_CALIBRATED = 0xE306 FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED = 0xE309 FRS_RECORDID_ROTATION_VECTOR = 0xE30B # Command IDs from section 6.4, page 42 # These are used to calibrate, initialize, set orientation, tare etc the sensor COMMAND_ERRORS = 1 COMMAND_COUNTER = 2 COMMAND_TARE = 3 COMMAND_INITIALIZE = 4 COMMAND_DCD = 6 COMMAND_ME_CALIBRATE = 7 COMMAND_DCD_PERIOD_SAVE = 9 COMMAND_OSCILLATOR = 10 COMMAND_CLEAR_DCD = 11 CALIBRATE_ACCEL = 0 CALIBRATE_GYRO = 1 CALIBRATE_MAG = 2 CALIBRATE_PLANAR_ACCEL = 3 CALIBRATE_ACCEL_GYRO_MAG = 4 CALIBRATE_STOP = 5 def normalize(v, tolerance=0.00001): mag2 = sum(n * n for n in v) if abs(mag2 - 1.0) > tolerance: mag = math.sqrt(mag2) v = tuple(n / mag for n in v) return v class BNO080: def __init__(self, i2, a = 0x4b): self.i2 = i2 self.a = a self.seqno = [0] * 8 if 1: self.sendPacket(CHANNEL_EXECUTABLE, [1]) time.sleep(0.150) while True: if not self.receivePacket(): break self.setFeature(SENSOR_REPORTID_ROTATION_VECTOR, 50000) def read_quaternion(self): while True: r = self.receivePacket() while r: tag = r[0] r = r[1:] if tag == 0xfb: # print("Time %d" % struct.unpack("I", r[:4])) r = r[4:] elif tag == SHTP_REPORT_COMMAND_RESPONSE: r = r[16:] elif tag == 0xfc: # print("Get Feature Response") r = r[17:] elif tag == SENSOR_REPORTID_ACCELEROMETER: r = r[10:] elif tag == SENSOR_REPORTID_ROTATION_VECTOR: (_,_,_,i,j,k,w,_) = struct.unpack(" 0): if preferred in self.devs: d1 = preferred else: d1 = min(self.devs) try: self.connect(self.devs[d1]) except: del self.devs[d1] d1 = None cb.Set(sorted(self.devs.keys())) if d1 is not None: cb.SetValue(d1) t = threading.Thread(target=ping_thr, args=(self, ), daemon=True) t.start() def start(self, rw): self.sd.start(self.addr, rw) self.started = True self.stop_button.Enable(True) def stop(self, e = None): self.sd.stop() self.started = False self.stop_button.Enable(False) def reset(self, e = None): self.sd.reset() self.started = False def write(self, htc, e): if (self.addr is not None) and htc.GetValue(): vv = [int(c,16) for c in htc.GetValue().split()] self.start(0) self.sd.write(vv) def read(self, e): n = int(self.rxCount.GetValue()) if self.addr is not None: self.start(1) r = self.sd.read(n) bb = struct.unpack("B"*n, r) self.rxVal.SetValue(" ".join(["%02X" % b for b in bb])) self.stop() def devices(self): if sys.platform in ('win32', 'cygwin'): return {pi.device: pi.device for pi in slp.comports()} elif sys.platform == 'darwin': devdir = "/dev/" pattern = "^cu.usbserial-(.*)" else: devdir = "/dev/serial/by-id/" pattern = "^usb-FTDI_FT230X_Basic_UART_(........)-" if not os.access(devdir, os.R_OK): return {} devs = os.listdir(devdir) def filter(d): m = re.match(pattern, d) if m: return (m.group(1), devdir + d) seldev = [filter(d) for d in devs] return dict([d for d in seldev if d]) def connect(self, dev): self.sd = i2cdriver.I2CDriver(dev) [w.Enable(True) for w in self.allw] self.refresh(None) def refresh(self, e): if self.sd and not self.monitor and not self.capture: lowhigh = ["LOW", "HIGH"] self.sd.getstatus() self.label_serial.SetLabel(self.sd.serial) self.label_voltage.SetLabel("%.2f V" % self.sd.voltage) self.label_current.SetLabel("%d mA" % self.sd.current) self.label_temp.SetLabel("%.1f C" % self.sd.temp) self.label_speed.SetSelection({100:0, 400:1}[self.sd.speed]) self.label_pullups.SetStringSelection(pullup_vals[self.sd.pullups & 7]) self.label_sda.SetLabel(lowhigh[self.sd.sda]) self.label_scl.SetLabel(lowhigh[self.sd.scl]) days = self.sd.uptime // (24 * 3600) rem = self.sd.uptime % (24 * 3600) hh = rem // 3600 mm = (rem // 60) % 60 ss = rem % 60; self.label_uptime.SetLabel("%d:%02d:%02d:%02d" % (days, hh, mm, ss)) [d.Enable(True) for d in self.dynamic] if not self.started and (self.sd.sda == 1) and (self.sd.scl == 1): devs = self.sd.scan(True) for i,l in self.heat.items(): self.hot(i, i in devs) def choose_device(self, e): self.connect(self.devs[e.EventObject.GetValue()]) def no_addr(self): [w.Enable(False) for w in self.dev_widgets] def choose_addr(self, e): o = e.EventObject v = o.GetValue() if v: self.addr = int(o.GetLabel(), 16) [w.Enable(True) for w in self.dev_widgets] def check_m(self, e): self.monitor = e.EventObject.GetValue() self.sd.monitor(self.monitor) [d.Enable(not self.monitor) for d in self.dynamic] if self.monitor: [self.hot(i, False) for i in self.heat] def check_c(self, e): global StopCapture cm = e.EventObject.GetValue() # self.sd.monitor(self.monitor) if cm: openFileDialog = wx.FileDialog(self, "CSV dump to file", "", "", "CSV files (*.csv)|*.csv", wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) openFileDialog.ShowModal() self.log_csv = openFileDialog.GetPath() openFileDialog.Destroy() if self.log_csv == u"": e.EventObject.SetValue(False) return StopCapture = False self.sd.dumpcount = 0 t = threading.Thread(target=capture_thr, args=(self.sd, self.log_csv)) t.setDaemon(True) t.start() else: StopCapture = True wx.MessageBox("Capture finished. %d events written to \"%s\"" % (self.sd.dumpcount, self.log_csv), "Message", wx.OK | wx.ICON_INFORMATION) while StopCapture: pass [d.Enable(not cm) for d in self.dynamic] if cm: [self.hot(i, False) for i in self.heat] self.capture = cm def set_speed(self, e): w = e.EventObject s = int(w.GetString(w.GetCurrentSelection())) self.sd.setspeed(s) def set_pullups(self, e): w = e.EventObject s = w.GetString(w.GetCurrentSelection()) code = pullup_vals.index(s) self.sd.setpullups(code | (code << 3)) def hot(self, i, s): l = self.heat[i] if s: l.SetForegroundColour((0,0,0)) l.SetFont(self.addrfonts[1]) else: l.SetForegroundColour((160,) * 3) l.SetFont(self.addrfonts[0]) l.Enable(s) if i == self.addr: [w.Enable(s) for w in self.dev_widgets] def main(): app = wx.App(0) try: f = Frame(*sys.argv[1:]) f.Show(True) app.MainLoop() except: import sys, traceback xc = traceback.format_exception(*sys.exc_info()) dlg = wx.MessageDialog(None, "".join(xc), "i2cgui Error Trap (%s)" % i2cdriver.__version__, wx.OK | wx.ICON_WARNING) dlg.ShowModal() dlg.Destroy() if __name__ == '__main__': main() ================================================ FILE: python3/samples/lcd1602.py ================================================ """ Example for LCD1602, in which a PCF8574 I/O expander drives a HD44780. Available from various vendors. Note that the modules require a 5V VCC; they don't function using the 3.3V VCC of I2CDriver. """ import sys import time import struct from i2cdriver import I2CDriver class HD44780: def __init__(self, i2, a = 0x27): self.i2 = i2 self.a = a self.nybble(3) # Enter 4-bit mode self.nybble(3) self.nybble(3) self.nybble(2) self.cmd(0x28) # 2 lines, 5x8 dot matrix self.cmd(0x0c) # display on self.cmd(0x06) # inc cursor to right when writing and don't scroll self.cmd(0x80) # set cursor to row 1, column 1 self.clear() def clear(self): """ Clear the screen """ self.cmd(0x01) time.sleep(.003) def show(self, line, text): """ Send string to LCD. Newline wraps to second line""" self.cmd({0:0x80, 1:0xc0}[line]) for c in text: self.data(ord(c)) def cmd(self, b): self.nybble(b >> 4) self.nybble(b & 0xf) time.sleep(.000053) def data(self, b): self.nybble(b >> 4, 1) self.nybble(b & 0xf, 1) # The PCF8574 outputs are connected to the HD44780 # pins as follows: # P0 RS (0: command, 1: data) # P1 R/W (0: write, 1: read) # P2 Enable/CLK # P3 Backlight control # P4-7 D4-D7 def nybble(self, n, rs = 0): bl = 8 | rs self.port( bl | (n << 4), bl | (n << 4) | 4, bl | (n << 4) ) def port(self, *bb): # Write bytes to port, setting the PCF8574 outputs self.i2.start(self.a, 0) self.i2.write(bb) self.i2.stop() if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = HD44780(i2) d.show(0, "HELLO WORLD") time.sleep(.5) d.show(1, "0123456789012345") ================================================ FILE: python3/samples/led8x8.py ================================================ """ Example for 8x8 LED Matrix modules, based on HT16K33. Available from multiple vendors. """ import sys import time from i2cdriver import I2CDriver font = open("cp437-8x8", "rb").read() from ht16k33 import HT16K33 class led8x8(HT16K33): def image(self, bb): """ Set the pixels to the bytes bb """ def swiz(b): bs = [str((b >> n) & 1) for n in range(8)] return int(bs[7] + bs[0] + bs[1] + bs[2] + bs[3] + bs[4] + bs[5] + bs[6], 2) bb = [swiz(b) for b in bb] self.load([b for s in zip(bb,bb) for b in s]) def char(self, c): """ Set the pixels to character c """ n = ord(c) ch = font[n * 8:n * 8 + 8] self.image(ch) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = led8x8(i2) for c in "I2C": d.char(c) time.sleep(1) ================================================ FILE: python3/samples/mag3110.py ================================================ """ Example Xtrinsic MAG3110 Three-Axis Digital Magnetometer Breakout available from Sparkfun. """ import sys import struct import time from i2cdriver import I2CDriver, EDS class MAG3110: def __init__(self, i2, a = 0x0e): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x10, 0b00000001) # CTRL_REG1. ACTIVE mode, 80 Hz conversions def rd(self): """ Read the measurement STATUS_REG and OUT_X,Y,Z """ return self.i2.regrd(self.a, 0x00, ">B3h") def measurement(self): """ Wait for a new field reading, return the (x,y,z) """ while True: (status, x, y, z) = self.rd() if status & 8: return (x, y, z) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.scan() d = MAG3110(i2) while 1: print(d.measurement()) ================================================ FILE: python3/samples/mux.py ================================================ import sys from i2cdriver import I2CDriver, EDS # Using a TCA9548A Low-Voltage 8-Channel I2C Switch # Three LM75B temperature sensors are connected to # channels 0,1 and 2. All are at address 0x48. class Mux: def __init__(self, i2, a = 0x70): self.i2 = i2 self.a = a def select(self, n): assert n in range(8) self.i2.start(self.a, 0) self.i2.write([1 << n]) self.i2.stop() if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) mux = Mux(i2) sensors = [ (0, EDS.Temp(i2)), (1, EDS.Temp(i2)), (2, EDS.Temp(i2)) ] # Reset all 8 channels for chan in range(8): mux.select(chan) i2.reset() def read(chan, dev): mux.select(chan) celsius = dev.read() return celsius while 1: print(" ".join(["%.1f" % read(chan, dev) for chan,dev in sensors])) ================================================ FILE: python3/samples/oled.py ================================================ """ Example for 128X64OLED Module Available from multiple vendors, e.g. DIYMall This example loads the I2CDriver logo onto the display, and flashes it four times. """ import sys import time from PIL import Image, ImageChops from i2cdriver import I2CDriver SETCONTRAST = 0x81 DISPLAYALLON_RESUME = 0xA4 DISPLAYALLON = 0xA5 NORMALDISPLAY = 0xA6 INVERTDISPLAY = 0xA7 DISPLAYOFF = 0xAE DISPLAYON = 0xAF SETDISPLAYOFFSET = 0xD3 SETCOMPINS = 0xDA SETVCOMDETECT = 0xDB SETDISPLAYCLOCKDIV = 0xD5 SETPRECHARGE = 0xD9 SETMULTIPLEX = 0xA8 SETLOWCOLUMN = 0x00 SETHIGHCOLUMN = 0x10 SETSTARTLINE = 0x40 MEMORYMODE = 0x20 COLUMNADDR = 0x21 PAGEADDR = 0x22 COMSCANINC = 0xC0 COMSCANDEC = 0xC8 SEGREMAP = 0xA0 CHARGEPUMP = 0x8D class OLED: def __init__(self, i2, a = 0x3c): self.i2 = i2 self.a = a self.command(DISPLAYOFF) self.command(SETDISPLAYCLOCKDIV, 0x80) # the suggested ratio 0x80 self.command(SETMULTIPLEX, 0x3f) self.command(SETDISPLAYOFFSET, 0) self.command(SETSTARTLINE | 0x0) self.command(CHARGEPUMP, 0x14) self.command(MEMORYMODE, 0) self.command(SEGREMAP | 0x1) self.command(COMSCANDEC) self.command(SETCOMPINS, 0x12) self.command(SETCONTRAST, 0xcf) self.command(SETVCOMDETECT, 0x40) self.command(DISPLAYALLON_RESUME) self.command(NORMALDISPLAY) self.im = Image.new("1", (128,64), 1) self.cls() def command(self, *c): assert(self.i2.start(self.a, 0)) assert(self.i2.write((0,) + c)) self.i2.stop() def image(self, im): for p in range(8): pr = self.im.crop((0,8*p,128,8*p+8)).transpose(Image.ROTATE_270) bb = im.crop((0,8*p,128,8*p+8)).transpose(Image.ROTATE_270) diff = ImageChops.difference(pr, bb) di = diff.getbbox() if di is not None: (x0, y0, x1, y1) = di self.command(COLUMNADDR) self.command(y0) self.command(y1 - 1) self.command(PAGEADDR) self.command(p) self.command(p + 1) self.i2.start(self.a, 0) self.i2.write([0x40]) self.i2.write(bb.tobytes()[y0:y1]) self.i2.stop() self.im = im self.command(DISPLAYON) def cls(self): self.image(Image.new("1", (128,64), 0)) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = OLED(i2) d.image(Image.open("logo.png").convert("1")) for i in range(4): d.command(INVERTDISPLAY) time.sleep(.5) d.command(NORMALDISPLAY) time.sleep(.5) ================================================ FILE: python3/samples/pca9685.py ================================================ import sys import time import random import struct from i2cdriver import I2CDriver class PCA9685: def __init__(self, i2, a = 0x40): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0x00, 0x20) # auto-increment mode def set(self, channel, t_on, t_off): assert 0 <= channel < 16 assert 0 <= t_on <= 0x1000 assert 0 <= t_off <= 0x1000 self.i2.regwr(self.a, 0x06 + 4 * channel, struct.pack("H", self.i2.read(2)) self.i2.stop() return r def read(self): """ return the joystick (x,y) position. The range is 0-1023. The center position of the joystick is approximately 512. """ # Note: their firmware requires two separate reads return (self.axis(0), self.axis(2)) if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = Joystick(i2) while 1: print(d.read()) time.sleep(.1) ================================================ FILE: python3/samples/qwiic-keypad.py ================================================ """ Example for Qwiic Keypad Available from Sparkfun. """ import sys import time import struct from i2cdriver import I2CDriver class Keypad: def __init__(self, i2, a = 0x4b): self.i2 = i2 self.a = a def read_ts(self): """ Return (key, timestamp) if pressed, or None. """ self.i2.start(self.a, 1) (k, age_in_ms) = struct.unpack(">BH", self.i2.read(3)) self.i2.stop() if k != 0: return (chr(k), time.time() - age_in_ms * .001) else: return None def read(self): r = self.read_ts() if r: return r[0] else: return None if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = Keypad(i2) while 1: print(d.read()) time.sleep(.1) ================================================ FILE: python3/samples/read-temperature.py ================================================ import sys import time from i2cdriver import I2CDriver, LM75B if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) d = LM75B(i2) for i in range(100): print(d.read()) time.sleep(.1) ================================================ FILE: python3/samples/tcr.py ================================================ import sys import struct from i2cdriver import I2CDriver class TCR: pass if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.setspeed(400) i2.scan() while 1: i2.start(0x0c, 1) b = i2.read(256) i2.stop() (l, ) = struct.unpack("> i) & 1) for i in range(12)] if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.reset() d = MPR121(i2) while 1: print(d.read()) time.sleep(.1) ================================================ FILE: python3/samples/wii.py ================================================ import sys import struct from i2cdriver import I2CDriver # # For details see # https://wiibrew.org/wiki/Wiimote/Extension_Controllers # class Wii: def __init__(self, i2, a = 0x52): self.i2 = i2 self.a = a self.i2.regwr(self.a, 0xf0, 0x55) self.i2.regwr(self.a, 0xfb, 0x00) idcode = (self.rdreg(0xfa, 6)) devices = { bytes([0x01, 0x00, 0xa4, 0x20, 0x01, 0x01]): self.wii_classic_pro, } if idcode in devices: self.rd = devices[idcode] else: raise IOError("Unrecognised device %r" % idcode) def rdreg(self, addr, n): self.i2.start(self.a, 0) self.i2.write([addr]) self.i2.stop() self.i2.start(self.a, 1) r = self.i2.read(n) self.i2.stop() return r def wii_classic_pro(self): b = self.rdreg(0x00, 6) r4 = '. brt b+ bh b- blt bdd bdr'.split() r = {id: 1 & (~b[4] >> i) for i,id in enumerate(r4)} r5 = 'bdu bdl bzr bx ba by bb bzl'.split() r.update({id: 1 & (~b[5] >> i) for i,id in enumerate(r5)}) r.update({ 'lx' : b[0] & 63, 'ly' : b[1] & 63, 'rx' : (((b[0] >> 6) & 3) << 3) | (((b[1] >> 6) & 3) << 1) | (((b[2] >> 7) & 1)), 'ry' : b[2] & 31, 'lt' : (((b[2] >> 5) & 3) << 3) | (((b[3] >> 5) & 7)), 'rt' : b[3] & 31, }) return r if __name__ == '__main__': i2 = I2CDriver(sys.argv[1]) i2.scan() d = Wii(i2) while True: print(d.rd()) ================================================ FILE: testall ================================================ #!/bin/sh set -e cd python3 pip install -e . python -c 'from i2cdriver import I2CDriver' cd .. cd c make -f linux/Makefile make -f linux/Makefile.clang