├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── githubci.yml ├── README.md ├── TinyWireM.cpp ├── TinyWireM.h ├── USI_TWI_Master.cpp ├── USI_TWI_Master.h ├── examples ├── Tiny85_Temp │ └── Tiny85_Temp.pde ├── Tiny85_Temp_LCD │ └── Tiny85_Temp_LCD.pde └── Tiny85_Temp_LCD_RTC │ └── Tiny85_Temp_LCD_RTC.pde ├── keywords.txt └── library.properties /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on an Adafruit Arduino library repository. To 2 | improve the speed of resolution please review the following guidelines and 3 | common troubleshooting steps below before creating the issue: 4 | 5 | - **Do not use GitHub issues for troubleshooting projects and issues.** Instead use 6 | the forums at http://forums.adafruit.com to ask questions and troubleshoot why 7 | something isn't working as expected. In many cases the problem is a common issue 8 | that you will more quickly receive help from the forum community. GitHub issues 9 | are meant for known defects in the code. If you don't know if there is a defect 10 | in the code then start with troubleshooting on the forum first. 11 | 12 | - **If following a tutorial or guide be sure you didn't miss a step.** Carefully 13 | check all of the steps and commands to run have been followed. Consult the 14 | forum if you're unsure or have questions about steps in a guide/tutorial. 15 | 16 | - **For Arduino projects check these very common issues to ensure they don't apply**: 17 | 18 | - For uploading sketches or communicating with the board make sure you're using 19 | a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes 20 | very hard to tell the difference between a data and charge cable! Try using the 21 | cable with other devices or swapping to another cable to confirm it is not 22 | the problem. 23 | 24 | - **Be sure you are supplying adequate power to the board.** Check the specs of 25 | your board and plug in an external power supply. In many cases just 26 | plugging a board into your computer is not enough to power it and other 27 | peripherals. 28 | 29 | - **Double check all soldering joints and connections.** Flakey connections 30 | cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints. 31 | 32 | - **Ensure you are using an official Arduino or Adafruit board.** We can't 33 | guarantee a clone board will have the same functionality and work as expected 34 | with this code and don't support them. 35 | 36 | If you're sure this issue is a defect in the code and checked the steps above 37 | please fill in the following fields to provide enough troubleshooting information. 38 | You may delete the guideline and text above to just leave the following details: 39 | 40 | - Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE** 41 | 42 | - Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO 43 | VERSION HERE** 44 | 45 | - List the steps to reproduce the problem below (if possible attach a sketch or 46 | copy the sketch code in too): **LIST REPRO STEPS BELOW** 47 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.github/workflows/githubci.yml: -------------------------------------------------------------------------------- 1 | name: Arduino Library CI 2 | 3 | on: [pull_request, push, repository_dispatch] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/setup-python@v4 11 | with: 12 | python-version: '3.x' 13 | - uses: actions/checkout@v3 14 | - uses: actions/checkout@v3 15 | with: 16 | repository: adafruit/ci-arduino 17 | path: ci 18 | 19 | - name: pre-install 20 | run: bash ci/actions_install.sh 21 | 22 | - name: test platforms 23 | run: python3 ci/build_platform.py trinket_3v trinket_5v gemma 24 | 25 | - name: clang 26 | run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r . 27 | 28 | - name: doxygen 29 | env: 30 | GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }} 31 | PRETTYNAME : "Adafruit TinyWireM Library" 32 | run: bash ci/doxy_gen_and_deploy.sh 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TinyWireM [![Build Status](https://github.com/adafruit/TinyWireM/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/TinyWireM/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/TinyWireM/html/index.html) 2 | 3 | ATtiny (e.g. Adafruit Trinket, Gemma) I2C library, adapted from BroHogan's code on Arduino Playground: http://playground.arduino.cc/Code/USIi2c 4 | 5 | Minor changes for consistency with the Arduino 1.0 Wire library (e.g. uses write() instead of send()). Buffer size slightly increased for Adafruit_LEDBackpack use. 6 | 7 | On the Trinket boards, pin #0 is SDA (I2C data), pin #2 is SCK (I2C clock). 8 | -------------------------------------------------------------------------------- /TinyWireM.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file TinyWireM.cpp 3 | * 4 | * @mainpage Adafruit TinyWireM Library 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * TinyWireM.cpp - a wrapper class for TWI/I2C Master library for the ATtiny on 9 | * Arduino 1/21/2011 BroHogan - brohoganx10 at gmail dot com 10 | * 11 | * **** See TinyWireM.h for Credits and Usage information **** 12 | * 13 | * @section license License 14 | * 15 | * This library is free software; you can redistribute it and/or modify it under 16 | * the terms of the GNU General Public License as published by the Free Software 17 | * Foundation; either version 2.1 of the License, or any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, but WITHOUT 20 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 21 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 22 | * details. 23 | */ 24 | 25 | extern "C" { 26 | //#include "USI_TWI_Master.h" 27 | //#include 28 | //#include 29 | //#include 30 | } 31 | 32 | #include "TinyWireM.h" 33 | #include "USI_TWI_Master.h" 34 | 35 | // Initialize Class Variables ////////////////////////////////////////////////// 36 | uint8_t USI_TWI::USI_Buf[USI_BUF_SIZE]; // holds I2C send and receive data 37 | uint8_t USI_TWI::USI_BufIdx = 0; // current number of bytes in the send buff 38 | uint8_t USI_TWI::USI_LastRead = 0; // number of bytes read so far 39 | uint8_t USI_TWI::USI_BytesAvail = 0; // number of bytes requested but not read 40 | 41 | // Constructors //////////////////////////////////////////////////////////////// 42 | 43 | USI_TWI::USI_TWI() {} 44 | 45 | // Public Methods ////////////////////////////////////////////////////////////// 46 | 47 | // int USI_TWI::peek(){} 48 | // void USI_TWI::flush(){} 49 | 50 | void USI_TWI::begin() { // initialize I2C lib 51 | USI_TWI_Master_Initialise(); 52 | } 53 | 54 | void USI_TWI::beginTransmission( 55 | uint8_t slaveAddr) { // setup address & write bit 56 | USI_BufIdx = 0; 57 | USI_Buf[USI_BufIdx] = (slaveAddr << TWI_ADR_BITS) | USI_SEND; 58 | } 59 | 60 | size_t USI_TWI::write(uint8_t data) { // buffers up data to send 61 | if (USI_BufIdx >= USI_BUF_SIZE - 1) 62 | return 0; // dont blow out the buffer 63 | USI_BufIdx++; // inc for next byte in buffer 64 | USI_Buf[USI_BufIdx] = data; 65 | return 1; 66 | } 67 | 68 | uint8_t USI_TWI::endTransmission() { return endTransmission(1); } 69 | 70 | uint8_t USI_TWI::endTransmission(uint8_t stop) { // actually sends the buffer 71 | bool xferOK = false; 72 | uint8_t errorCode = 0; 73 | xferOK = USI_TWI_Start_Read_Write( 74 | USI_Buf, USI_BufIdx + 1); // core func that does the work 75 | USI_BufIdx = 0; 76 | if (xferOK) { 77 | if (stop) { 78 | errorCode = USI_TWI_Master_Stop(); 79 | if (errorCode == 0) { 80 | errorCode = USI_TWI_Get_State_Info(); 81 | return errorCode; 82 | } 83 | } 84 | return 0; 85 | } else { // there was an error 86 | errorCode = 87 | USI_TWI_Get_State_Info(); // this function returns the error number 88 | return errorCode; 89 | } 90 | } 91 | 92 | uint8_t 93 | USI_TWI::requestFrom(uint8_t slaveAddr, 94 | uint8_t numBytes) { // setup for receiving from slave 95 | bool xferOK = false; 96 | uint8_t errorCode = 0; 97 | USI_LastRead = 0; 98 | USI_BytesAvail = numBytes; // save this off in a global 99 | numBytes++; // add extra byte to transmit header 100 | USI_Buf[0] = 101 | (slaveAddr << TWI_ADR_BITS) | USI_RCVE; // setup address & Rcve bit 102 | xferOK = USI_TWI_Start_Read_Write(USI_Buf, 103 | numBytes); // core func that does the work 104 | // USI_Buf now holds the data read 105 | if (xferOK) { 106 | errorCode = USI_TWI_Master_Stop(); 107 | if (errorCode == 0) { 108 | errorCode = USI_TWI_Get_State_Info(); 109 | return errorCode; 110 | } 111 | return 0; 112 | } else { // there was an error 113 | errorCode = 114 | USI_TWI_Get_State_Info(); // this function returns the error number 115 | return errorCode; 116 | } 117 | } 118 | 119 | int USI_TWI::read() { // returns the bytes received one at a time 120 | USI_LastRead++; // inc first since first uint8_t read is in USI_Buf[1] 121 | return USI_Buf[USI_LastRead]; 122 | } 123 | 124 | int USI_TWI::available() { // the bytes available that haven't been read yet 125 | return USI_BytesAvail - (USI_LastRead); 126 | } 127 | 128 | void USI_TWI::end() { USI_TWI_Master_Stop(); } 129 | 130 | // Preinstantiate Objects ////////////////////////////////////////////////////// 131 | 132 | /*! 133 | * @brief Makes TinyWireM an object of USI_TWI 134 | */ 135 | USI_TWI TinyWireM = USI_TWI(); 136 | -------------------------------------------------------------------------------- /TinyWireM.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file TinyWireM.h 3 | * 4 | * TinyWireM.h - a wrapper(+) class for TWI/I2C Master library for the ATtiny on 5 | *Arduino 1/21/2011 BroHogan - brohoganx10 at gmail dot com 6 | * 7 | * Thanks to 'jkl' for the gcc version of Atmel's USI_TWI_Master code 8 | * http://www.cs.cmu.edu/~dst/ARTSI/Create/PC%20Comm/ 9 | * I added Atmel's original Device dependant defines section back into 10 | *USI_TWI_Master.h 11 | * 12 | * 13 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! More so 14 | *than with the Wire lib. 15 | * 16 | * USAGE is modeled after the standard Wire library . . . 17 | * Put in setup(): 18 | * TinyWireM.begin(){ // initialize I2C lib 19 | * To Send: 20 | * TinyWireM.beginTransmission(uint8_t slaveAddr){ // setup slave's 21 | *address (7 bit address - same as Wire) TinyWireM.send(uint8_t data){ // buffer 22 | *up bytes to send - can be called multiple times someByte = 23 | *TinyWireM.endTransmission(){ // actually send the bytes in the buffer 24 | * // returns (optional) 0 25 | *= sucess or see USI_TWI_Master.h for error codes To Receive: someByte = 26 | *TinyWireM.requestFrom(uint8_t slaveAddr, uint8_t numBytes){ // reads 27 | *'numBytes' from slave's address 28 | * // (usage optional) 29 | *returns 0= success or see USI_TWI_Master.h for error codes someByte = 30 | *TinyWireM.receive(){ // returns the next byte in the received 31 | *buffer - called multiple times someByte = TinyWireM.available(){ // returns 32 | *the number of unread bytes in the received buffer 33 | * 34 | * TODO: (by others!) 35 | * - merge this class with TinyWireS for master & slave support in one 36 | *library 37 | * 38 | * This library is free software; you can redistribute it and/or modify it 39 | *under the terms of the GNU General Public License as published by the Free 40 | *Software Foundation; either version 2.1 of the License, or any later version. 41 | * This program is distributed in the hope that it will be useful, but WITHOUT 42 | *ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 43 | *FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 44 | *details. 45 | */ 46 | 47 | #ifndef TinyWireM_h 48 | #define TinyWireM_h 49 | 50 | #include "Arduino.h" 51 | #include 52 | #define USI_SEND 0 //!< indicates sending to TWI 53 | #define USI_RCVE 1 //!< indicates receiving from TWI 54 | #define USI_BUF_SIZE 18 //!< bytes in message buffer 55 | 56 | /*! 57 | * @brief class USI_TWI : public Stream 58 | */ 59 | class USI_TWI { 60 | private: 61 | static uint8_t USI_Buf[]; // holds I2C send and receive data 62 | static uint8_t USI_BufIdx; // current number of bytes in the send buff 63 | static uint8_t USI_LastRead; // number of bytes read so far 64 | static uint8_t USI_BytesAvail; // number of bytes requested but not read 65 | 66 | public: 67 | USI_TWI(); 68 | /*! 69 | * @brief Initialize library for main function 70 | */ 71 | void begin(); 72 | /*! 73 | * @brief Setup address & write bit 74 | * @param slaveAddr Secondary device address 75 | */ 76 | void beginTransmission(uint8_t); 77 | /*! 78 | * @brief Buffers up data to send 79 | * @param data Data to send 80 | * @return Returns 1 when successful 81 | */ 82 | size_t write(uint8_t); 83 | /*! 84 | * @brief Sends data 85 | * @param d Data buffer 86 | * @param n How much data to send 87 | * @return Returns 1 when successful 88 | */ 89 | inline size_t write(uint8_t *d, uint8_t n) { 90 | uint16_t i; 91 | for (i = 0; i < n; i++) 92 | write(d[i]); 93 | return (size_t)n; 94 | } 95 | /*! 96 | * @brief Sends data 97 | * @param n Data to send 98 | * @return Returns 1 when successful 99 | */ 100 | inline size_t write(unsigned long n) { return write((uint8_t)n); } 101 | /*! 102 | * @brief Sends data 103 | * @param n Data to send 104 | * @return Returns 1 when successful 105 | */ 106 | inline size_t write(long n) { return write((uint8_t)n); } 107 | /*! 108 | * @brief Sends data 109 | * @param n Data to send 110 | * @return Returns 1 when successful 111 | */ 112 | inline size_t write(unsigned int n) { return write((uint8_t)n); } 113 | /*! 114 | * @brief Sends data 115 | * @param n Data to send 116 | * @return Returns 1 when successful 117 | */ 118 | inline size_t write(int n) { return write((uint8_t)n); } 119 | /*! 120 | * @brief Buffers up data to send 121 | * @param b Data to send 122 | * @return Returns 1 when successful 123 | */ 124 | void send(uint8_t b) { write(b); } 125 | /*! 126 | * @brief Sends data 127 | * @param d Buffer to send from 128 | * @param n How much to send from buffer 129 | * @return Returns 1 when successful 130 | */ 131 | void send(uint8_t *d, uint8_t n) { write(d, n); } 132 | /*! 133 | * @brief Sends data 134 | * @param n Data to send 135 | * @return Returns 1 when successful 136 | */ 137 | void send(int n) { write((uint8_t)n); } 138 | /*! 139 | * @brief Ends the transmission 140 | * @return Returns the error code if there was one 141 | */ 142 | uint8_t endTransmission(); 143 | /*! 144 | * @brief Ends the transmission 145 | * @param stop Buffer to send to end the transmission 146 | * @return Returns the error code if there was one 147 | */ 148 | uint8_t endTransmission(uint8_t); 149 | /*! 150 | * @brief Setup for receiving from secondary 151 | * @param slaveAddr Secondary device address 152 | * @param numBytes How many bytes to request 153 | * @return Returns 0, if there was an error, returns the error code 154 | */ 155 | uint8_t requestFrom(uint8_t, uint8_t); 156 | /*! 157 | * @brief Returns the bytes received one at a time 158 | * @return Returns the bytes received one at a time 159 | */ 160 | int read(); 161 | /*! 162 | * @brief The bytes available htat haven't been read yet 163 | * @return Returns how many bytes are available 164 | */ 165 | int available(); 166 | /*! 167 | * @brief Returns the top value 168 | * @return Returns the top value 169 | */ 170 | int peek(void); 171 | /*! 172 | * @brief Flushes the buffer 173 | */ 174 | void flush(void); 175 | /*! 176 | * @brief Receives data from the device 177 | * @return Returns the data 178 | */ 179 | uint8_t receive(void) { 180 | int c = read(); 181 | if (c < 0) 182 | return 0; 183 | return c; 184 | } 185 | /*! 186 | * @brief Function for generating a TWI Stop Condition. Used to release 187 | * the TWI bus 188 | */ 189 | void end(); 190 | }; 191 | 192 | extern USI_TWI TinyWireM; 193 | 194 | #endif 195 | -------------------------------------------------------------------------------- /USI_TWI_Master.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file USI_TWI_Master.cpp 3 | */ 4 | /***************************************************************************** 5 | * 6 | * 7 | * File USI_TWI_Master.c compiled with gcc 8 | * Date Friday, 10/31/08 Boo! 9 | * Updated by jkl 10 | * 11 | 12 | * AppNote : AVR310 - Using the USI module as a TWI Master 13 | * 14 | * Extensively modified to provide complete I2C driver. 15 | * 16 | *Notes: 17 | * - T4_TWI and T2_TWI delays are modified to work with 1MHz 18 | default clock * and now use hard code values. They would need to 19 | change * for other clock rates. Refer to the Apps Note. 20 | * 21 | * 12/17/08 Added USI_TWI_Start_Memory_Read Routine -jkl 22 | * Note msg buffer will have slave adrs ( with write bit set) and 23 | memory adrs; 24 | * length should be these two bytes plus the number of 25 | bytes to read. 26 | ****************************************************************************/ 27 | #include "USI_TWI_Master.h" 28 | #include 29 | #include 30 | #include 31 | 32 | /*! 33 | * @brief USI Transmit and receive function 34 | * @param msg Pointer to the location of the msg buffer 35 | * @param msgSize How much data to send from the buffer 36 | * @return Returns true if transmission was successful 37 | */ 38 | unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *, 39 | unsigned char); 40 | unsigned char USI_TWI_Master_Transfer(unsigned char); 41 | unsigned char USI_TWI_Master_Start(void); 42 | 43 | /*! 44 | * @brief Stores the state of the USI_TWI 45 | */ 46 | union USI_TWI_state { 47 | unsigned char errorState; //!< Can reuse the TWI_state for error states since 48 | //!< it will not be needed if there is an error. 49 | /*! 50 | * @brief Struct that stores the modes for the device 51 | */ 52 | struct { 53 | unsigned char addressMode : 1; //!< Address mode 54 | unsigned char masterWriteDataMode : 1; //!< Write data mode 55 | unsigned char memReadMode : 1; //!< Read memory mode 56 | unsigned char unused : 5; //!< Unused 57 | }; 58 | } USI_TWI_state; //!< USI_TWI_state The state of the USI_TWI 59 | 60 | /*! 61 | * @brief USI TWI single master initialization function 62 | */ 63 | void USI_TWI_Master_Initialise(void) { 64 | PORT_USI |= 65 | (1 66 | << PIN_USI_SDA); // Enable pullup on SDA, to set high as released state. 67 | PORT_USI |= 68 | (1 69 | << PIN_USI_SCL); // Enable pullup on SCL, to set high as released state. 70 | 71 | DDR_USI |= (1 << PIN_USI_SCL); // Enable SCL as output. 72 | DDR_USI |= (1 << PIN_USI_SDA); // Enable SDA as output. 73 | 74 | USIDR = 0xFF; // Preload dataregister with "released level" data. 75 | USICR = (0 << USISIE) | (0 << USIOIE) | // Disable Interrupts. 76 | (1 << USIWM1) | (0 << USIWM0) | // Set USI in Two-wire mode. 77 | (1 << USICS1) | (0 << USICS0) | 78 | (1 << USICLK) | // Software stobe as counter clock source 79 | (0 << USITC); 80 | USISR = (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | 81 | (1 << USIDC) | // Clear flags, 82 | (0x0 << USICNT0); // and reset counter. 83 | } 84 | 85 | /*! 86 | * @brief Use this function to get hold of the error message from the last 87 | * transmission 88 | * @return Returns error state 89 | */ 90 | unsigned char USI_TWI_Get_State_Info(void) { 91 | return (USI_TWI_state.errorState); // Return error state. 92 | } 93 | /*! 94 | * @brief USI Random (memory) Read function. This function sets up for call 95 | * to USI_TWI_Start_Transceiver_With_Data which does the work. 96 | * Doesn't matter if read/write bit is set or cleared, it'll be set 97 | * correctly in this function. 98 | * 99 | * The msgSize is passed to USI_TWI_Start_Transceiver_With_Data. 100 | * 101 | * Success or error code is returned. Error codes are defined in 102 | * USI_TWI_Master.h 103 | * @param msg Pointer to the buffer that contains the messages to be read 104 | * @param msgSize How much to read from the buffer 105 | * @return Returns the message read 106 | */ 107 | unsigned char USI_TWI_Start_Random_Read(unsigned char *msg, 108 | unsigned char msgSize) { 109 | *(msg) &= ~(TRUE << TWI_READ_BIT); // clear the read bit if it's set 110 | USI_TWI_state.errorState = 0; 111 | USI_TWI_state.memReadMode = TRUE; 112 | 113 | return (USI_TWI_Start_Transceiver_With_Data(msg, msgSize)); 114 | } 115 | /*! 116 | * @brief USI Normal Read / Write Function 117 | * Transmit and receive function. LSB of first byte in buffer 118 | * indicates if a read or write cycles is performed. If set a read 119 | * operation is performed. 120 | * 121 | * Function generates (Repeated) Start Condition, sends address and 122 | * R/W, Reads/Writes Data, and verifies/sends ACK. 123 | * 124 | * Success or error code is returned. Error codes are defined in 125 | * USI_TWI_Master.h 126 | * @param msg Pointer to the buffer that has the messages 127 | * @param msgSize The size of the message 128 | * @return Returns the data read 129 | */ 130 | unsigned char USI_TWI_Start_Read_Write(unsigned char *msg, 131 | unsigned char msgSize) { 132 | 133 | USI_TWI_state.errorState = 0; // Clears all mode bits also 134 | 135 | return (USI_TWI_Start_Transceiver_With_Data(msg, msgSize)); 136 | } 137 | /*! 138 | * @brief USI Transmit and receive function. LSB of first byte in buffer 139 | * indicates if a read or write cycles is performed. If set a read 140 | * operation is performed. 141 | * 142 | * Function generates (Repeated) Start Condition, sends address and 143 | * R/W, Reads/Writes Data, and verifies/sends ACK. 144 | * 145 | * This function also handles Random Read function if the memReadMode 146 | * bit is set. In that case, the function will: 147 | * The address in memory will be the second 148 | * byte and is written *without* sending a STOP. 149 | * Then the Read bit is set (lsb of first byte), the byte count is 150 | * adjusted (if needed), and the function function starts over by sending 151 | * the slave address again and reading the data. 152 | * 153 | * Success or error code is returned. Error codes are defined in 154 | * USI_TWI_Master.h 155 | * @param msg Pointer to the location of the msg buffer 156 | * @param msgSize How much data to send from the buffer 157 | */ 158 | unsigned char USI_TWI_Start_Transceiver_With_Data(unsigned char *msg, 159 | unsigned char msgSize) { 160 | unsigned char const tempUSISR_8bit = 161 | (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | 162 | (1 << USIDC) | // Prepare register value to: Clear flags, and 163 | (0x0 << USICNT0); // set USI to shift 8 bits i.e. count 16 clock edges. 164 | unsigned char const tempUSISR_1bit = 165 | (1 << USISIF) | (1 << USIOIF) | (1 << USIPF) | 166 | (1 << USIDC) | // Prepare register value to: Clear flags, and 167 | (0xE << USICNT0); // set USI to shift 1 bit i.e. count 2 clock edges. 168 | unsigned char *savedMsg; 169 | unsigned char savedMsgSize; 170 | 171 | // This clear must be done before calling this function so that memReadMode 172 | // can be specified. 173 | // USI_TWI_state.errorState = 0; // Clears all 174 | // mode bits also 175 | 176 | USI_TWI_state.addressMode = TRUE; // Always true for first byte 177 | 178 | #ifdef PARAM_VERIFICATION 179 | if (msg > (unsigned char *)RAMEND) // Test if address is outside SRAM space 180 | { 181 | USI_TWI_state.errorState = USI_TWI_DATA_OUT_OF_BOUND; 182 | return (FALSE); 183 | } 184 | if (msgSize <= 1) // Test if the transmission buffer is empty 185 | { 186 | USI_TWI_state.errorState = USI_TWI_NO_DATA; 187 | return (FALSE); 188 | } 189 | #endif 190 | 191 | #ifdef NOISE_TESTING // Test if any unexpected conditions have arrived prior to 192 | // this execution. 193 | if (USISR & (1 << USISIF)) { 194 | USI_TWI_state.errorState = USI_TWI_UE_START_CON; 195 | return (FALSE); 196 | } 197 | if (USISR & (1 << USIPF)) { 198 | USI_TWI_state.errorState = USI_TWI_UE_STOP_CON; 199 | return (FALSE); 200 | } 201 | if (USISR & (1 << USIDC)) { 202 | USI_TWI_state.errorState = USI_TWI_UE_DATA_COL; 203 | return (FALSE); 204 | } 205 | #endif 206 | 207 | if (!(*msg & 208 | (1 << TWI_READ_BIT))) // The LSB in the address byte determines if is a 209 | // masterRead or masterWrite operation. 210 | { 211 | USI_TWI_state.masterWriteDataMode = TRUE; 212 | } 213 | 214 | // if (USI_TWI_state.memReadMode) 215 | // { 216 | savedMsg = msg; 217 | savedMsgSize = msgSize; 218 | // } 219 | 220 | if (!USI_TWI_Master_Start()) { 221 | return (FALSE); // Send a START condition on the TWI bus. 222 | } 223 | 224 | /*Write address and Read/Write data */ 225 | do { 226 | /* If masterWrite cycle (or inital address tranmission)*/ 227 | if (USI_TWI_state.addressMode || USI_TWI_state.masterWriteDataMode) { 228 | /* Write a byte */ 229 | PORT_USI &= ~(1 << PIN_USI_SCL); // Pull SCL LOW. 230 | USIDR = *(msg++); // Setup data. 231 | USI_TWI_Master_Transfer(tempUSISR_8bit); // Send 8 bits on bus. 232 | 233 | /* Clock and verify (N)ACK from slave */ 234 | DDR_USI &= ~(1 << PIN_USI_SDA); // Enable SDA as input. 235 | if (USI_TWI_Master_Transfer(tempUSISR_1bit) & (1 << TWI_NACK_BIT)) { 236 | if (USI_TWI_state.addressMode) 237 | USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_ADDRESS; 238 | else 239 | USI_TWI_state.errorState = USI_TWI_NO_ACK_ON_DATA; 240 | return (FALSE); 241 | } 242 | 243 | if ((!USI_TWI_state.addressMode) && 244 | USI_TWI_state 245 | .memReadMode) // means memory start address has been written 246 | { 247 | msg = savedMsg; // start at slave address again 248 | *(msg) |= (TRUE << TWI_READ_BIT); // set the Read Bit on Slave address 249 | USI_TWI_state.errorState = 0; 250 | USI_TWI_state.addressMode = TRUE; // Now set up for the Read cycle 251 | msgSize = savedMsgSize; // Set byte count correctly 252 | // NOte that the length should be Slave adrs byte + # bytes to read + 1 253 | // (gets decremented below) 254 | if (!USI_TWI_Master_Start()) { 255 | USI_TWI_state.errorState = USI_TWI_BAD_MEM_READ; 256 | return (FALSE); // Send a START condition on the TWI bus. 257 | } 258 | } else { 259 | USI_TWI_state.addressMode = 260 | FALSE; // Only perform address transmission once. 261 | } 262 | } 263 | /* Else masterRead cycle*/ 264 | else { 265 | /* Read a data byte */ 266 | DDR_USI &= ~(1 << PIN_USI_SDA); // Enable SDA as input. 267 | *(msg++) = USI_TWI_Master_Transfer(tempUSISR_8bit); 268 | 269 | /* Prepare to generate ACK (or NACK in case of End Of Transmission) */ 270 | if (msgSize == 1) // If transmission of last byte was performed. 271 | { 272 | USIDR = 0xFF; // Load NACK to confirm End Of Transmission. 273 | } else { 274 | USIDR = 0x00; // Load ACK. Set data register bit 7 (output for SDA) low. 275 | } 276 | USI_TWI_Master_Transfer(tempUSISR_1bit); // Generate ACK/NACK. 277 | } 278 | } while (--msgSize); // Until all data sent/received. 279 | 280 | // usually a stop condition is sent here, but TinyWireM needs to choose 281 | // whether or not to send it 282 | 283 | /* Transmission successfully completed*/ 284 | return (TRUE); 285 | } 286 | 287 | /*! 288 | * @brief Core function for shifting data in and out from the USI. 289 | * Data to be sent has to be placed into the USIDR prior to calling 290 | * this function. Data read, will be return'ed from the function. 291 | * @param temp Temperature to set the USISR 292 | * @return Returns the temp read from the device 293 | */ 294 | unsigned char USI_TWI_Master_Transfer(unsigned char temp) { 295 | USISR = temp; // Set USISR according to temp. 296 | // Prepare clocking. 297 | temp = (0 << USISIE) | (0 << USIOIE) | // Interrupts disabled 298 | (1 << USIWM1) | (0 << USIWM0) | // Set USI in Two-wire mode. 299 | (1 << USICS1) | (0 << USICS0) | 300 | (1 << USICLK) | // Software clock strobe as source. 301 | (1 << USITC); // Toggle Clock Port. 302 | do { 303 | _delay_us(T2_TWI); 304 | USICR = temp; // Generate positve SCL edge. 305 | while (!(PIN_USI & (1 << PIN_USI_SCL))) 306 | ; // Wait for SCL to go high. 307 | _delay_us(T4_TWI); 308 | USICR = temp; // Generate negative SCL edge. 309 | } while (!(USISR & (1 << USIOIF))); // Check for transfer complete. 310 | 311 | _delay_us(T2_TWI); 312 | temp = USIDR; // Read out data. 313 | USIDR = 0xFF; // Release SDA. 314 | DDR_USI |= (1 << PIN_USI_SDA); // Enable SDA as output. 315 | 316 | return temp; // Return the data from the USIDR 317 | } 318 | /*! 319 | * @brief Function for generating a TWI Start Condition. 320 | * @return Returns true if the signal can be verified, otherwise returns false 321 | */ 322 | unsigned char USI_TWI_Master_Start(void) { 323 | /* Release SCL to ensure that (repeated) Start can be performed */ 324 | PORT_USI |= (1 << PIN_USI_SCL); // Release SCL. 325 | while (!(PORT_USI & (1 << PIN_USI_SCL))) 326 | ; // Verify that SCL becomes high. 327 | _delay_us(T2_TWI); 328 | 329 | /* Generate Start Condition */ 330 | PORT_USI &= ~(1 << PIN_USI_SDA); // Force SDA LOW. 331 | _delay_us(T4_TWI); 332 | PORT_USI &= ~(1 << PIN_USI_SCL); // Pull SCL LOW. 333 | PORT_USI |= (1 << PIN_USI_SDA); // Release SDA. 334 | 335 | #ifdef SIGNAL_VERIFY 336 | if (!(USISR & (1 << USISIF))) { 337 | USI_TWI_state.errorState = USI_TWI_MISSING_START_CON; 338 | return (FALSE); 339 | } 340 | #endif 341 | return (TRUE); 342 | } 343 | /*! 344 | * @brief Function for generating a TWI Stop Condition. Used to release 345 | * the TWI bus. 346 | * @return Returns true if it was successful 347 | */ 348 | unsigned char USI_TWI_Master_Stop(void) { 349 | PORT_USI &= ~(1 << PIN_USI_SDA); // Pull SDA low. 350 | PORT_USI |= (1 << PIN_USI_SCL); // Release SCL. 351 | while (!(PIN_USI & (1 << PIN_USI_SCL))) 352 | ; // Wait for SCL to go high. 353 | _delay_us(T4_TWI); 354 | PORT_USI |= (1 << PIN_USI_SDA); // Release SDA. 355 | _delay_us(T2_TWI); 356 | 357 | #ifdef SIGNAL_VERIFY 358 | if (!(USISR & (1 << USIPF))) { 359 | USI_TWI_state.errorState = USI_TWI_MISSING_STOP_CON; 360 | return (FALSE); 361 | } 362 | #endif 363 | 364 | return (TRUE); 365 | } 366 | -------------------------------------------------------------------------------- /USI_TWI_Master.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file USI_TWI_Master.h 3 | */ 4 | /***************************************************************************** 5 | * 6 | * 7 | * File USI_TWI_Master.h compiled with gcc 8 | * Date Friday, 10/31/08 Boo! 9 | * Updated by jkl 10 | * 11 | * 12 | * Supported devices : All device with USI module can be used. 13 | * The example is written for the ATtiny2313 14 | * 15 | * AppNote : AVR310 - Using the USI module as a TWI Master 16 | * 17 | * This is modified to just do I2C communication on ATtiny2313 running at 18 | * 1MHz. Fast mode is probably possible, but would need a faster clock 19 | * and has not been tested. 20 | * 21 | * 12/15/08 Added declaration of USI_TWI_Start_Memory_Read -jkl 22 | ****************************************************************************/ 23 | 24 | //********** Defines **********// 25 | 26 | // Defines controlling timing limits - SCL <= 100KHz. 27 | 28 | // For use with _delay_us() 29 | #define T2_TWI 5 //!< >4,7us 30 | #define T4_TWI 4 //!< >4,0us 31 | 32 | // Defines error code generating 33 | //#define PARAM_VERIFICATION 34 | //#define NOISE_TESTING 35 | #define SIGNAL_VERIFY //!< Verifies the signal is correct. This should probably 36 | //!< be on always. 37 | 38 | /**************************************************************************** 39 | Bit and byte definitions 40 | ****************************************************************************/ 41 | #define TWI_READ_BIT 0 //!< Bit position for R/W bit in "address byte". 42 | #define TWI_ADR_BITS \ 43 | 1 //!< Bit position for LSB of the slave address bits in the init byte. 44 | #define TWI_NACK_BIT 0 //!< Bit position for (N)ACK bit. 45 | 46 | // Note these have been renumbered from the Atmel Apps Note. Most likely errors 47 | // are now 48 | // lowest numbers so they're easily recognized as LED flashes. 49 | #define USI_TWI_NO_DATA 0x08 //!< Transmission buffer is empty 50 | #define USI_TWI_DATA_OUT_OF_BOUND \ 51 | 0x09 //!< Transmission buffer is outside SRAM space 52 | #define USI_TWI_UE_START_CON 0x07 //!< Unexpected Start Condition 53 | #define USI_TWI_UE_STOP_CON 0x06 //!< Unexpected Stop Condition 54 | #define USI_TWI_UE_DATA_COL 0x05 //!< Unexpected Data Collision (arbitration) 55 | #define USI_TWI_NO_ACK_ON_DATA 0x02 //!< The slave did not acknowledge all data 56 | #define USI_TWI_NO_ACK_ON_ADDRESS \ 57 | 0x01 //!< The slave did not acknowledge the address 58 | #define USI_TWI_MISSING_START_CON \ 59 | 0x03 //!< Generated Start Condition not detected on bus 60 | #define USI_TWI_MISSING_STOP_CON \ 61 | 0x04 //!< Generated Stop Condition not detected on bus 62 | #define USI_TWI_BAD_MEM_READ 0x0A //!< Error during external memory read 63 | 64 | // Device dependant defines ADDED BACK IN FROM ORIGINAL ATMEL .H 65 | 66 | #if defined(__AVR_AT90Mega169__) | defined(__AVR_ATmega169__) | \ 67 | defined(__AVR_AT90Mega165__) | defined(__AVR_ATmega165__) | \ 68 | defined(__AVR_ATmega325__) | defined(__AVR_ATmega3250__) | \ 69 | defined(__AVR_ATmega645__) | defined(__AVR_ATmega6450__) | \ 70 | defined(__AVR_ATmega329__) | defined(__AVR_ATmega3290__) | \ 71 | defined(__AVR_ATmega649__) | defined(__AVR_ATmega6490__) 72 | #define DDR_USI DDRE 73 | #define PORT_USI PORTE 74 | #define PIN_USI PINE 75 | #define PORT_USI_SDA PORTE5 76 | #define PORT_USI_SCL PORTE4 77 | #define PIN_USI_SDA PINE5 78 | #define PIN_USI_SCL PINE4 79 | #endif 80 | 81 | #if defined(__AVR_ATtiny25__) | defined(__AVR_ATtiny45__) | \ 82 | defined(__AVR_ATtiny85__) | defined(__AVR_AT90Tiny26__) | \ 83 | defined(__AVR_ATtiny26__) 84 | #define DDR_USI DDRB 85 | #define PORT_USI PORTB 86 | #define PIN_USI PINB 87 | #define PORT_USI_SDA PORTB0 88 | #define PORT_USI_SCL PORTB2 89 | #define PIN_USI_SDA PINB0 90 | #define PIN_USI_SCL PINB2 91 | #endif 92 | 93 | #if defined(__AVR_ATtiny84__) | defined(__AVR_ATtiny44__) 94 | #define DDR_USI DDRA 95 | #define PORT_USI PORTA 96 | #define PIN_USI PINA 97 | #define PORT_USI_SDA PORTA6 98 | #define PORT_USI_SCL PORTA4 99 | #define PIN_USI_SDA PINA6 100 | #define PIN_USI_SCL PINA4 101 | #endif 102 | 103 | #if defined(__AVR_AT90Tiny2313__) | defined(__AVR_ATtiny2313__) 104 | #define DDR_USI DDRB 105 | #define PORT_USI PORTB 106 | #define PIN_USI PINB 107 | #define PORT_USI_SDA PORTB5 108 | #define PORT_USI_SCL PORTB7 109 | #define PIN_USI_SDA PINB5 110 | #define PIN_USI_SCL PINB7 111 | #endif 112 | 113 | /* From the original .h 114 | // Device dependant defines - These for ATtiny2313. // CHANGED FOR ATtiny85 115 | 116 | #define DDR_USI DDRB 117 | #define PORT_USI PORTB 118 | #define PIN_USI PINB 119 | #define PORT_USI_SDA PORTB0 // was PORTB5 - N/U 120 | #define PORT_USI_SCL PORTB2 // was PORTB7 - N/U 121 | #define PIN_USI_SDA PINB0 // was PINB5 122 | #define PIN_USI_SCL PINB2 // was PINB7 123 | */ 124 | 125 | // General defines 126 | #define TRUE 1 //!< True 127 | #define FALSE 0 //!< False 128 | 129 | //********** Prototypes **********// 130 | 131 | void USI_TWI_Master_Initialise(void); 132 | unsigned char USI_TWI_Start_Random_Read(unsigned char *, unsigned char); 133 | unsigned char USI_TWI_Start_Read_Write(unsigned char *, unsigned char); 134 | unsigned char USI_TWI_Master_Stop(void); 135 | unsigned char USI_TWI_Get_State_Info(void); 136 | -------------------------------------------------------------------------------- /examples/Tiny85_Temp/Tiny85_Temp.pde: -------------------------------------------------------------------------------- 1 | /* ATtiny85 as an I2C Master Ex1 BroHogan 1/21/11 2 | * I2C master reading DS1621 temperature sensor. (display with leds) 3 | * SETUP: 4 | * ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) LED3 5 | * ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND 6 | * ATtiny Pin 5 = SDA on DS1621 ATtiny Pin 6 = (D1) to LED2 7 | * ATtiny Pin 7 = SCK on DS1621 ATtiny Pin 8 = VCC (2.7-5.5V) 8 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! 9 | * DS1621 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x48 10 | * TinyWireM USAGE & CREDITS: - see TinyWireM.h 11 | * NOTES: 12 | * The ATtiny85 + DS1621 draws 1.7mA @5V when leds are not on and not reading temp. 13 | * Using sleep mode, they draw .2 @5V @ idle - see http://brownsofa.org/blog/archives/261 14 | */ 15 | 16 | #include // I2C Master lib for ATTinys which use USI 17 | 18 | #define DS1621_ADDR 0x48 // 7 bit I2C address for DS1621 temperature sensor 19 | #define LED1_PIN 4 // ATtiny Pin 3 20 | #define LED2_PIN 1 // ATtiny Pin 6 21 | #define LED3_PIN 3 // ATtiny Pin 2 22 | 23 | int tempC = 0; // holds temp in C 24 | int tempF = 0; // holds temp in F 25 | 26 | 27 | void setup(){ 28 | pinMode(LED1_PIN,OUTPUT); 29 | pinMode(LED2_PIN,OUTPUT); 30 | pinMode(LED3_PIN,OUTPUT); 31 | Blink(LED1_PIN,2); // show it's alive 32 | TinyWireM.begin(); // initialize I2C lib 33 | Init_Temp(); // Setup DS1621 34 | delay (3000); 35 | } 36 | 37 | 38 | void loop(){ 39 | Get_Temp(); 40 | Blink(LED1_PIN,tempC/10); // blink 10's of temperature on LED 1 41 | delay (1000); 42 | Blink(LED2_PIN,tempC%10); // blink 1's of temperature on LED 2 43 | delay (4000); // wait a few sec before next reading 44 | } 45 | 46 | 47 | void Init_Temp(){ // Setup the DS1621 for one-shot mode 48 | TinyWireM.beginTransmission(DS1621_ADDR); 49 | TinyWireM.send(0xAC); // Access Command Register 50 | TinyWireM.send(B00000001); // Using one-shot mode for battery savings 51 | //TinyWireM.send(B00000000); // if setting continious mode for fast reads 52 | TinyWireM.endTransmission(); // Send to the slave 53 | } 54 | 55 | 56 | void Get_Temp(){ // Get the temperature from a DS1621 57 | TinyWireM.beginTransmission(DS1621_ADDR); 58 | TinyWireM.send(0xEE); // if one-shot, start conversions now 59 | TinyWireM.endTransmission(); // Send 1 byte to the slave 60 | delay(750); // if one-shot, must wait ~750 ms for conversion 61 | TinyWireM.beginTransmission(DS1621_ADDR); 62 | TinyWireM.send(0xAA); // read temperature (for either mode) 63 | TinyWireM.endTransmission(); // Send 1 byte to the slave 64 | TinyWireM.requestFrom(DS1621_ADDR,1); // Request 1 byte from slave 65 | tempC = TinyWireM.receive(); // get the temperature 66 | tempF = tempC * 9 / 5 + 32; // convert to Fahrenheit 67 | } 68 | 69 | 70 | void Blink(byte led, byte times){ // poor man's GUI 71 | for (byte i=0; i< times; i++){ 72 | digitalWrite(led,HIGH); 73 | delay (400); 74 | digitalWrite(led,LOW); 75 | delay (175); 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /examples/Tiny85_Temp_LCD/Tiny85_Temp_LCD.pde: -------------------------------------------------------------------------------- 1 | /* ATtiny85 as an I2C Master Ex2 BroHogan 1/21/11 2 | * I2C master reading DS1621 temperature sensor. Display to I2C GPIO LED. 3 | * SETUP: 4 | * ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) N/U 5 | * ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND 6 | * ATtiny Pin 5 = SDA on DS1621 & GPIO ATtiny Pin 6 = (D1) to LED2 7 | * ATtiny Pin 7 = SCK on DS1621 & GPIO ATtiny Pin 8 = VCC (2.7-5.5V) 8 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! 9 | * DS1621 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x48 10 | * PCA8574A GPIO was used wired per instructions in "info" folder in the LiquidCrystal_I2C lib. 11 | * This ex assumes A0-A2 are set HIGH for an addeess of 0x3F 12 | * LiquidCrystal_I2C lib was modified for ATtiny - on Playground with TinyWireM lib. 13 | * TinyWireM USAGE & CREDITS: - see TinyWireM.h 14 | */ 15 | 16 | //#define DEBUG 17 | #include // I2C Master lib for ATTinys which use USI 18 | #include // for LCD w/ GPIO MODIFIED for the ATtiny85 19 | 20 | #define GPIO_ADDR 0x3F // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A 21 | #define DS1621_ADDR 0x48 // 7 bit I2C address for DS1621 temperature sensor 22 | #define LED1_PIN 4 // ATtiny Pin 3 23 | #define LED2_PIN 1 // ATtiny Pin 6 24 | 25 | int tempC = 0; // holds temp in C 26 | int tempF = 0; // holds temp in F 27 | 28 | LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines 29 | 30 | 31 | void setup(){ 32 | #ifdef DEBUG 33 | pinMode(LED1_PIN,OUTPUT); 34 | pinMode(LED2_PIN,OUTPUT); 35 | Blink(LED1_PIN,2); // show it's alive 36 | #endif 37 | TinyWireM.begin(); // initialize I2C lib 38 | Init_Temp(); // Setup DS1621 39 | lcd.init(); // initialize the lcd 40 | lcd.backlight(); // Print a message to the LCD. 41 | lcd.print("Hello, Temp!"); 42 | delay (2000); 43 | } 44 | 45 | 46 | void loop(){ 47 | Get_Temp(); // read current temperature 48 | lcd.clear(); // display it 49 | lcd.print("C: "); 50 | lcd.print(tempC,DEC); 51 | lcd.setCursor(7,0); 52 | lcd.print("F: "); 53 | lcd.print(tempF,DEC); 54 | #ifdef DEBUG 55 | Blink(LED1_PIN,tempC/10); // blink 10's of temperature on LED 1 56 | delay (1000); 57 | Blink(LED2_PIN,tempC%10); // blink 1's of temperature on LED 2 58 | #endif 59 | delay (4000); // wait a few sec before next reading 60 | } 61 | 62 | 63 | void Init_Temp(){ // Setup the DS1621 for one-shot mode 64 | TinyWireM.beginTransmission(DS1621_ADDR); 65 | TinyWireM.send(0xAC); // Access Command Register 66 | TinyWireM.send(B00000001); // Using one-shot mode for battery savings 67 | //TinyWireM.send(B00000000); // if setting continious mode for fast reads 68 | TinyWireM.endTransmission(); // Send to the slave 69 | } 70 | 71 | 72 | void Get_Temp(){ // Get the temperature from a DS1621 73 | TinyWireM.beginTransmission(DS1621_ADDR); 74 | TinyWireM.send(0xEE); // if one-shot, start conversions now 75 | TinyWireM.endTransmission(); // Send 1 byte to the slave 76 | delay(750); // if one-shot, must wait ~750 ms for conversion 77 | TinyWireM.beginTransmission(DS1621_ADDR); 78 | TinyWireM.send(0xAA); // read temperature (for either mode) 79 | TinyWireM.endTransmission(); // Send 1 byte to the slave 80 | TinyWireM.requestFrom(DS1621_ADDR,1); // Request 1 byte from slave 81 | tempC = TinyWireM.receive(); // get the temperature 82 | tempF = tempC * 9 / 5 + 32; // convert to Fahrenheit 83 | } 84 | 85 | 86 | #ifdef DEBUG 87 | void Blink(byte led, byte times){ // poor man's GUI 88 | for (byte i=0; i< times; i++){ 89 | digitalWrite(led,HIGH); 90 | delay (400); 91 | digitalWrite(led,LOW); 92 | delay (175); 93 | } 94 | } 95 | #endif 96 | 97 | -------------------------------------------------------------------------------- /examples/Tiny85_Temp_LCD_RTC/Tiny85_Temp_LCD_RTC.pde: -------------------------------------------------------------------------------- 1 | /* ATtiny85 as an I2C Master Ex3 BroHogan 1/22/11 2 | * I2C master reading DS1621 temperature sensor & DS1307 RTC. Display to I2C GPIO LED. 3 | * SETUP: 4 | * ATtiny Pin 1 = (RESET) N/U ATtiny Pin 2 = (D3) N/U 5 | * ATtiny Pin 3 = (D4) to LED1 ATtiny Pin 4 = GND 6 | * ATtiny Pin 5 = SDA on all devices ATtiny Pin 6 = (D1) to LED2 7 | * ATtiny Pin 7 = SCK on all devices ATtiny Pin 8 = VCC (2.7-5.5V) 8 | * NOTE! - It's very important to use pullups on the SDA & SCL lines! 9 | * DS1621 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x48 10 | * DS1307 wired per data sheet. This ex assumes A0-A2 are set LOW for an addeess of 0x68 11 | * PCA8574A GPIO was used wired per instructions in "info" folder in the LiquidCrystal_I2C lib. 12 | * This ex assumes A0-A2 are set HIGH for an addeess of 0x3F 13 | * LiquidCrystal_I2C lib was modified for ATtiny - on Playground with TinyWireM lib. 14 | * TinyWireM USAGE & CREDITS: - see TinyWireM.h 15 | */ 16 | 17 | //#define DEBUG 18 | #include // I2C Master lib for ATTinys which use USI 19 | #include // for LCD w/ GPIO MODIFIED for the ATtiny85 20 | 21 | #define GPIO_ADDR 0x3F // (PCA8574A A0-A2 @5V) typ. A0-A3 Gnd 0x20 / 0x38 for A 22 | #define DS1307_ADDR 0x68 // I2C real time clock 23 | #define DS1621_ADDR 0x48 // 7 bit I2C address for DS1621 temperature sensor 24 | #define LED1_PIN 4 // ATtiny Pin 3 25 | #define LED2_PIN 1 // ATtiny Pin 6 26 | //#define HR24 true 27 | 28 | int tempC = 0; // holds temp in C 29 | int tempF = 0; // holds temp in F 30 | byte seconds,minutes,hours,day_of_week,days,months,years,PM,hour12,DST; 31 | char timeString[10]; // HH:MM 12 Hr. no AM/PM or 24 Hr (based on param) 32 | char dateString[10]; // MM/DD or DD/MM (based on param)- no year 33 | bool HR24; // 12/24 Hr Time and date 34 | 35 | LiquidCrystal_I2C lcd(GPIO_ADDR,16,2); // set address & 16 chars / 2 lines 36 | 37 | 38 | void setup(){ 39 | #ifdef DEBUG 40 | pinMode(LED1_PIN,OUTPUT); 41 | pinMode(LED2_PIN,OUTPUT); 42 | Blink(LED1_PIN,3); // show it's alive 43 | #endif 44 | TinyWireM.begin(); // initialize I2C lib 45 | Init_Temp(); // Setup DS1621 46 | lcd.init(); // initialize the lcd 47 | lcd.backlight(); // Print a message to the LCD. 48 | lcd.print("Hello, Temp!"); 49 | delay (2000); 50 | } 51 | 52 | 53 | void loop(){ 54 | Get_Temp(); // read current temperature 55 | Get_Time(); // read current time 56 | lcd.clear(); // display it 57 | lcd.print("C"); 58 | lcd.print((char)223); 59 | lcd.print(": "); 60 | lcd.print(tempC,DEC); 61 | lcd.setCursor(9,0); 62 | lcd.print("F"); 63 | lcd.print((char)223); 64 | lcd.print(": "); 65 | lcd.print(tempF,DEC); 66 | lcd.setCursor(0,1); 67 | lcd.print(timeString); 68 | lcd.setCursor(9,1); 69 | lcd.print(dateString); 70 | #ifdef DEBUG 71 | Blink(LED1_PIN,tempC/10); // blink 10's of temperature on LED 1 72 | delay (1000); 73 | Blink(LED2_PIN,tempC%10); // blink 1's of temperature on LED 2 74 | #endif 75 | HR24 = ! HR24; // flip the format 76 | delay (4000); // wait a few sec before next reading 77 | } 78 | 79 | 80 | void Init_Temp(){ // Setup the DS1621 for one-shot mode 81 | TinyWireM.beginTransmission(DS1621_ADDR); 82 | TinyWireM.send(0xAC); // Access Command Register 83 | TinyWireM.send(B00000001); // Using one-shot mode for battery savings 84 | //TinyWireM.send(B00000000); // if setting continious mode for fast reads 85 | TinyWireM.endTransmission(); // Send to the slave 86 | } 87 | 88 | 89 | void Get_Temp(){ // Get the temperature from a DS1621 90 | TinyWireM.beginTransmission(DS1621_ADDR); 91 | TinyWireM.send(0xEE); // if one-shot, start conversions now 92 | TinyWireM.endTransmission(); // Send 1 byte to the slave 93 | delay(750); // if one-shot, must wait ~750 ms for conversion 94 | TinyWireM.beginTransmission(DS1621_ADDR); 95 | TinyWireM.send(0xAA); // read temperature (for either mode) 96 | TinyWireM.endTransmission(); // Send 1 byte to the slave 97 | TinyWireM.requestFrom(DS1621_ADDR,1); // Request 1 byte from slave 98 | tempC = TinyWireM.receive(); // get the temperature 99 | tempF = tempC * 9 / 5 + 32; // convert to Fahrenheit 100 | } 101 | 102 | 103 | void Get_Time(){ // get the time and date from the DS1307 chip 104 | byte wireRet = 0; 105 | memset(timeString,0,sizeof(timeString)); // initialize the strings 106 | memset(dateString,0,sizeof(dateString)); 107 | 108 | TinyWireM.beginTransmission(DS1307_ADDR); // reset DS1307 register pointer 109 | TinyWireM.send(0); 110 | wireRet = TinyWireM.endTransmission(); 111 | if (wireRet) { // report any send esrrors 112 | lcd.clear(); 113 | lcd.print("SendError: "); 114 | lcd.print(wireRet,DEC); 115 | delay(1500); 116 | } 117 | wireRet = TinyWireM.requestFrom(DS1307_ADDR, 7); // request 7 bytes from DS1307 118 | if (wireRet) { // report any receive esrrors 119 | lcd.clear(); 120 | lcd.print("RcveError: "); 121 | lcd.print(wireRet,DEC); 122 | delay(1500); 123 | } 124 | #ifdef DEBUG 125 | lcd.clear(); 126 | lcd.print("Before Reads: "); 127 | lcd.print(TinyWireM.available(),DEC); // testing TinyWireM.available() 128 | delay(1500); 129 | #endif 130 | seconds = bcdToDec(TinyWireM.receive()); // handle the 7 bytes received 131 | minutes = bcdToDec(TinyWireM.receive()); 132 | hours = bcdToDec(TinyWireM.receive()); 133 | day_of_week = TinyWireM.receive(); 134 | days = bcdToDec(TinyWireM.receive()); 135 | months = bcdToDec(TinyWireM.receive()); 136 | years = bcdToDec(TinyWireM.receive()); 137 | #ifdef DEBUG 138 | lcd.clear(); 139 | lcd.print("After Reads: "); 140 | lcd.print(TinyWireM.available(),DEC); // testing TinyWireM.available() 141 | delay(1500); 142 | #endif 143 | // deal with AM/PM global and 12 hour clock 144 | if (hours >= 12) PM = true; 145 | else PM = false; 146 | if (hours > 12)hour12 = hours - 12; 147 | else hour12 = hours; 148 | if (hours == 0) hour12 = 12; 149 | 150 | // make time string 151 | if (HR24) AppendToString (hours,timeString); // add 24 hour time to string 152 | else AppendToString (hour12,timeString); // add 12 hour time to string 153 | strcat(timeString,":"); 154 | if (minutes < 10) strcat(timeString,"0"); 155 | AppendToString (minutes,timeString); // add MINUTES to string 156 | if (!HR24){ 157 | if (hours >= 12) strcat(timeString," PM"); // deal with AM/PM 158 | else strcat(timeString," AM"); 159 | } 160 | // make date string 161 | if (HR24)AppendToString (days,dateString); // add DAY to string 162 | else AppendToString (months,dateString); // add MONTH to string 163 | strcat(dateString,"/"); 164 | if (HR24)AppendToString (months,dateString); // add MONTH to string 165 | else AppendToString (days,dateString); // add DAY to string 166 | strcat(dateString,"/"); 167 | if (years < 10) strcat(dateString,"0"); 168 | AppendToString (years,dateString); // add YEAR to string 169 | } 170 | 171 | 172 | void AppendToString (byte bValue, char *pString){ // appends a byte to string passed 173 | char tempStr[6]; 174 | memset(tempStr,'\0',sizeof(tempStr)); 175 | itoa(bValue,tempStr,10); 176 | strcat(pString,tempStr); 177 | } 178 | 179 | 180 | byte bcdToDec(byte val) { // Convert binary coded decimal to normal decimal numbers 181 | return ((val / 16 * 10) + (val % 16)); 182 | } 183 | 184 | 185 | #ifdef DEBUG 186 | void Blink(byte led, byte times){ // poor man's GUI 187 | for (byte i=0; i< times; i++){ 188 | digitalWrite(led,HIGH); 189 | delay (400); 190 | digitalWrite(led,LOW); 191 | delay (175); 192 | } 193 | } 194 | #endif 195 | 196 | 197 | 198 | 199 | 200 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For TinyWireM 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | ####################################### 10 | # Methods and Functions (KEYWORD2) 11 | ####################################### 12 | 13 | begin KEYWORD2 14 | beginTransmission KEYWORD2 15 | endTransmission KEYWORD2 16 | requestFrom KEYWORD2 17 | write KEYWORD2 18 | read KEYWORD2 19 | end KEYWORD2 20 | 21 | ####################################### 22 | # Instances (KEYWORD2) 23 | ####################################### 24 | 25 | TinyWireM KEYWORD2 26 | 27 | ####################################### 28 | # Constants (LITERAL1) 29 | ####################################### 30 | 31 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=TinyWireM 2 | version=1.1.3 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=I2C library for Trinket and Gemma, adapted from BroHogan's code on Arduino Playground 6 | paragraph=I2C library for Trinket and Gemma, adapted from BroHogan's code on Arduino Playground 7 | category=Signal Input/Output 8 | url=https://github.com/adafruit/TinyWireM 9 | architectures=* 10 | --------------------------------------------------------------------------------