Menu

I2C Compile issue for ATTiny84a

Adam Sharp
2025-06-11
2025-06-14
  • Adam Sharp

    Adam Sharp - 2025-06-11

    New to GCB and the first few test projects I created have worked OK. So I appologise if I paosted incorrectly. I did do some searches for a similar issue, but pinned nothing down.

    Moved onto something more complicated with being an I2C Slave on an ATTiny84a. I have attached a ZIP of the files that I think are relevant. Let me know if you need anything else.

    GCB version: 1.76.2 Release: 23074

    Basically the code appears to referance TW (Twin Wire) hardware, but the 84a uses a USI (Universal Serial Interface) for I2C communications. So when you compile you get an undeclared register (TWCR). Which is not surprising as the hardware is USIxxxx.

    Am I in error, or the compiler?

    Many thanks,
    Adam.

     
  • Anobium

    Anobium - 2025-06-12

    Hello Adam,

    These chips use USI for TWI and the GCBASIC library assume the TWI registers not the USI.

    You can implement the USI will some ease but it may be a lot easier to use software I2C for your solution.

     
  • Adam Sharp

    Adam Sharp - 2025-06-13

    Anobium,

    Thank you for your reply. I had worked out that theT84 (and a range of other Atmel devices) used different hardware for I2C. It is a shame that the USI hardware is not supported by GCB currently.

    Although I'm well versed with BASIC, sadly I'm not in a position to write the required GCB code to support I2C via USI at this time. For this project, I shall return to using C/C++, where the relevant hardware libraries already exist. The project timelines do not have resources to code and test drivers. And I'm not conversant enough with GCB and I2C at this time to make a good job of such a task. I'm not interested in bit banging an implementation for an I2C slave. Various forums (including AVRFreaks) indicate that I2C slave bit banging is unreliable on this hardware.

    If you have a link to implementing such addons so that such a library can be included into any T84 project automatically (not via include, but detected by the compilation process), I'll gladly take a look in the future. But it appears today, that GCB does not fully support the T84 hardware (and other models that use USI).

    Could this be noted in the GCB IC2 documentation that USI based devices are NOT supported please.

    Adam.

     
    • Anobium

      Anobium - 2025-06-13

      If the C libraries are published then porting is a relatively easy task. The datasheet was vague on how to use USI.

       
  • Adam Sharp

    Adam Sharp - 2025-06-14

    If that is the case. Do you want a link for a good library, or do you have some notes to port and I'll take a bash?

     
  • Anobium

    Anobium - 2025-06-14

    :-)

    Post what source is out there.

     
    • Adam Sharp

      Adam Sharp - 2025-06-14

      https://github.com/rambo/TinyWire/tree/master/TinyWireS

      There are plenty of Master libraries to choose from.

      There are also Atmel Application Notes: 310 and 312 covering using the USI as TWI. Covering Master and Slave modes respectively.

       
  • Anobium

    Anobium - 2025-06-14

    Here is an untested implementation of USI I2C Slave

    • GCBASIC library for USI TWI (I2C) Slave driver on ATtiny84A
    • Implements TWI slave functionality using USI module
    • Based on Atmel AVR312: Using the USI module as an I2C slave
    • Created for ATtiny84A with SDA on PA6 and SCL on PA4

    What Does it Do?

    The main loop in the the example GCBASIC program that demonstrates how to use the USI library functions to configure an ATtiny84A microcontroller as an I2C slave device.

    Functionality

    1. Initializes the ATtiny84A as an I2C Slave:
    2. Sets the I2C slave address to 0x20 (32 in decimal) using USI_TWI_Slave_Init(0x20).
    3. Configures the USI module to handle I2C communication (SDA on PA6, SCL on PA4).
    4. Runs a Loop to Process I2C Data:
    5. Checks if data is available in the receive buffer using USI_TWI_Available().
    6. If data is available, reads a byte using USI_TWI_Read().
    7. Writes the received byte plus 1 back to the transmit buffer using USI_TWI_Write(Data + 1).
    8. This creates an "echo + 1" behavior: if the master sends 0x05, the slave responds with 0x06.

    Purpose: It’s a simple test program to verify the I2C slave functionality. The slave responds to I2C write requests by storing received data and to read requests by sending back the last received data incremented by 1.

    1. Set Up the Hardware

    Microcontroller: Use an ATtiny84A (or ATtiny84, as they’re compatible).
    I2C Pins:
    SDA: PA6 (pin 7 on the 14-pin SOIC package).
    SCL: PA4 (pin 9).
    Pull-Up Resistors: Connect 4.7kΩ pull-up resistors from SDA and SCL to VCC (typically 3.3V or 5V, matching your setup).
    Power Supply: Connect VCC and GND to a stable 3.3V or 5V supply. The code assumes an 8 MHz internal oscillator, so no external crystal is needed unless you’ve changed the fuses.
    I2C Master: Use a microcontroller (e.g., Arduino with Wire library), Raspberry Pi, or I2C master device to communicate with the ATtiny84A. Connect the master’s SDA and SCL pins to the ATtiny84A’s PA6 and PA4, ensuring a common ground.

    1. Test with an I2C Master
      Write Test:
      Use an I2C master to send data to address 0x20.
      Example (Arduino with Wire library):
    #include <Wire.h>
    
    #define SLAVE_ADDRESS 0x20 // I2C address of ATtiny84A (set in main.gcb)
    #define TEST_BYTE 0x05    // Byte to send to the slave
    
    void setup() {
      // Initialize I2C as master
      Wire.begin();
    
      // Initialize Serial for debugging
      Serial.begin(9600);
      Serial.println("I2C Master Test Program Started");
    }
    
    void loop() {
      // Write test byte to slave
      Serial.print("Sending 0x");
      Serial.print(TEST_BYTE, HEX);
      Serial.print(" to address 0x");
      Serial.println(SLAVE_ADDRESS, HEX);
    
      Wire.beginTransmission(SLAVE_ADDRESS);
      Wire.write(TEST_BYTE); // Send 0x05
      int writeResult = Wire.endTransmission();
    
      if (writeResult == 0) {
        Serial.println("Write successful");
      } else {
        Serial.print("Write failed with error: ");
        Serial.println(writeResult);
      }
    
      // Wait briefly to ensure slave processes the write
      delay(10);
    
      // Read one byte from slave
      Serial.print("Reading from address 0x");
      Serial.println(SLAVE_ADDRESS, HEX);
    
      Wire.requestFrom(SLAVE_ADDRESS, 1); // Request 1 byte
      if (Wire.available()) {
        byte received = Wire.read();
        Serial.print("Received: 0x");
        Serial.println(received, HEX); // Should print 0x06 (TEST_BYTE + 1)
      } else {
        Serial.println("No data received");
      }
    
      // Wait before next test
      Serial.println("---");
      delay(1000);
    }
    

    The ATtiny84A will receives 0x05, stores it in TWI_RxBuf, and adds 0x06 to TWI_TxBuf.

     
    • Adam Sharp

      Adam Sharp - 2025-06-14

      Many thanks for the prompt support and example. I have a hardware setup on the bench and should be able to take a look-see tomorrow. I will report back. However, power outages here are not helping anything, hopeully they will be cleared up overnight.

       
      • Anobium

        Anobium - 2025-06-14

        The logic will need testing and validating. It may, or it may not work. :-)

         

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.