ATTiny85 1 — ATtiny85 simulation

An interactive ATtiny85 circuit simulation you can run free in your browser on Velxio, by ian7171.

Components

Sketch code

#define F_CPU 8000000UL // Is slower than the CPU but for this is fine

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>
#include <stdint.h>
#include "functions.h"

#define SDA PB0
#define SCL PB2
#define OLED_ADDR 0x3C


static void oled_init(void)
{
    _delay_ms(100);

    oled_cmd(0xAE); // Display off
    oled_cmd(0xD5); oled_cmd(0x80); // Set display clock ... to 0x80 freq
    oled_cmd(0xA8); oled_cmd(0x3F); // Set display height ... to 0x3F (63 rows 0 to 63)
    oled_cmd(0xD3); oled_cmd(0x00); // Set display offset ... to 0
    oled_cmd(0x40); // Set display line to start at 0 (i.e. from the top)
    oled_cmd(0x8D); oled_cmd(0x14); // Charge pump ... enabled
    oled_cmd(0x20); oled_cmd(0x02); // Set memory address mode to ... page mode (0 to 127 pixels, 8 pixels high = top row, then page 2 is next row down)

    oled_cmd(0xA1);
    oled_cmd(0xC8);

    oled_cmd(0xDA);
    oled_cmd(0x12);

    oled_cmd(0x81);
    oled_cmd(0xCF);

    oled_cmd(0xD9);
    oled_cmd(0xF1);

    oled_cmd(0xDB);
    oled_cmd(0x40);

    oled_cmd(0xA4);
    oled_cmd(0xA6);

    oled_cmd(0xAF);
}



static void i2c_stop(void)
{
    PORTB &= ~(1 << SDA);
    _delay_us(5);

    PORTB |= (1 << SCL);
    _delay_us(5);

    PORTB |= (1 << SDA);
    _delay_us(5);
}


/* =========================================================
   SEND ONE BYTE USING USI SHIFT REGISTER
   ========================================================= */

static uint8_t usi_write_byte(uint8_t value)
{
    USIDR = value;

    /*
       16 edges = 8 complete clock cycles
    */
    USISR = (1 << USIOIF);

    do
    {
        USICR =
            (1 << USIWM1) |
            (1 << USICS1) |
            (1 << USICLK) |
            (1 << USITC);

        while (!(PINB & (1 << SCL)));

        _delay_us(2);

        USICR =
            (1 << USIWM1) |
            (1 << USICS1) |
            (1 << USICLK) |
            (1 << USITC);

        _delay_us(2);

    }
    while (!(USISR & (1 << USIOIF)));


    /*
       ACK cycle
    */

    DDRB &= ~(1 << SDA);       // release SDA

    USIDR = 0xFF;

    USISR =
        (1 << USIOIF) |
        0x0E;                  // one clock remaining


    do
    {
        USICR =
            (1 << USIWM1) |
            (1 << USICS1) |
            (1 << USICLK) |
            (1 << USITC);

        while (!(PINB & (1 << SCL)));

        _delay_us(2);

        USICR =
            (1 << USIWM1) |
            (1 << USICS1) |
            (1 << USICLK) |
            (1 << USITC);

    }
    while (!(USISR & (1 << USIOIF)));


    uint8_t ack =
        !(USIDR & 0x01);


    DDRB |= (1 << SDA);

    return ack;
}


/* =========================================================
   SSD1306 COMMAND
   ========================================================= */

static void oled_cmd(uint8_t command)
{
    i2c_start();

    usi_write_byte(OLED_ADDR << 1);

    usi_write_byte(0x00);

    usi_write_byte(command);

    i2c_stop();
}


/* =======================

More projects by ian7171