Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/mytechnotalent/atmega328p_ssd1306_driver

An ATmega328P SSD1306 driver written entirely in Assembler.
https://github.com/mytechnotalent/atmega328p_ssd1306_driver

arduino arduino-platform arduino-programming assembler assembly atmega328p avr avr-programming avrdude ssd1306

Last synced: 28 days ago
JSON representation

An ATmega328P SSD1306 driver written entirely in Assembler.

Awesome Lists containing this project

README

        

## FREE Reverse Engineering Self-Study Course [HERE](https://github.com/mytechnotalent/Reverse-Engineering-Tutorial)


# ATmega328P SSD1306 Driver
An ATmega328P SSD1306 driver written entirely in Assembler.


# Code
```assembler
; ===================================================================
; Project: ATmega328P SSD1306 Driver
; ===================================================================
; Author: Kevin Thomas
; E-Mail: [email protected]
; Version: 1.0
; Date: 01/09/25
; Target Device: ATmega328P (Arduino Nano)
; Clock Frequency: 16 MHz
; Toolchain: AVR-AS, AVRDUDE
; License: Apache License 2.0
; Description: This program is a simple SSD1306 driver that works
; capital letters.
; ===================================================================

; ===================================================================
; SYMBOLIC DEFINITIONS
; ===================================================================
.equ TWBR, 0xB8 ; TWI Bit Rate Register
.equ TWSR, 0xB9 ; TWI Status Register
.equ TWDR, 0xBB ; TWI Data Register
.equ TWCR, 0xBC ; TWI Control Register
.equ TWINT, 7 ; TWI Interrupt Flag
.equ TWEA, 6 ; TWI Enable Acknowledge
.equ TWSTA, 5 ; TWI Start Condition
.equ TWSTO, 4 ; TWI Stop Condition
.equ TWEN, 2 ; TWI Enable Bit
.equ SSD1306_ADDR, 0x3C ; SSD1306 I2C Address

; ===================================================================
; PROGRAM ENTRY POINT
; ===================================================================
.global program ; global label; make avail external
.section .text ; start of the .text (code) section

; ===================================================================
; PROGRAM LOOP
; ===================================================================
; Description: Main program loop which executes all subroutines and
; then repeats indefinitely.
; -------------------------------------------------------------------
; Instructions: AVR Instruction Set Manual
; 6.87 RCALL – Relative Call to Subroutine
; 6.95 LDI – Load Immediate
; 6.90 RJMP – Relative Jump
; ===================================================================
program:
rcall TWI_init ; initialize TWI
rcall SSD1306_init ; initialize SSD1306
rcall SSD1306_clear ; clear the OLED screen
ldi r16, 0 ; set page to 0
rcall set_cursor_page ; move cursor to page 0
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 1 ; set page to 1
rcall set_cursor_page ; move cursor to page 1
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 2 ; set page to 2
rcall set_cursor_page ; move cursor to page 2
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 3 ; set page to 3
rcall set_cursor_page ; move cursor to page 3
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 4 ; set page to 4
rcall set_cursor_page ; move cursor to page 4
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 5 ; set page to 5
rcall set_cursor_page ; move cursor to page 5
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 6 ; set page to 6
rcall set_cursor_page ; move cursor to page 6
rcall display_text_KEVIN_T ; display "KEVIN T"
ldi r16, 7 ; set page to 7
rcall set_cursor_page ; move cursor to page 7
rcall display_text_KEVIN_T ; display "KEVIN T"
program_loop:
rjmp program_loop ; infinite loop

; ===================================================================
; SUBROUTINE: TWI_init
; ===================================================================
; Description: Initializes the Two-Wire Interface (TWI/I2C) module
; on the ATmega128P for communication at ~100kHz.
; -------------------------------------------------------------------
; Instructions: AVR Instruction Set Manual
; 6.95 LDI – Load Immediate
; 6.117 STS – Store Direct to Data Space
; 6.88 RET – Return from Subroutine
; ===================================================================
TWI_init:
; -----------------------------------------------------------------
; STEP 1: Set TWI Prescaler to 1
; -----------------------------------------------------------------
ldi r16, 0x00 ; load immediate val 0x00 into r16
; 0x00 sets TWI Prescaler bits
; (TWPS1:0) to 0
; prescaler value: 1 (as 4^TWPS)
sts TWSR, r16 ; store the value in TWI Status
; Register (TWSR)
; TWSR[1:0] (TWPS1, TWPS0) set the
; prescaler
; -----------------------------------------------------------------
; STEP 2: Set TWI Bit Rate Register for ~100kHz
; -----------------------------------------------------------------
ldi r16, 72 ; load immediate value 72 into r16
; this value sets the SCL freq
; SCL = F_CPU /
; (16 + 2 * TWBR * 4^TWPS)
; for F_CPU = 16MHz, TWPS = 1,
; TWBR = 72:
; SCL ≈ 100kHz
sts TWBR, r16 ; store the value in TWI Bit Rate
; Register (TWBR)
; TWBR determines the SCL freq
; -----------------------------------------------------------------
; STEP 3: Enable TWI Module
; -----------------------------------------------------------------
ldi r16, (1 << TWEN) ; load immediate value with TWEN
; bit set
; TWEN (TWI Enable Bit) enables the
; TWI hardware
sts TWCR, r16 ; store the value in TWI Control
; Register (TWCR)
; TWCR enables TWI operations with
; TWEN
ret ; return from subroutine

; ===================================================================
; SUBROUTINE: TWI_write_byte
; ===================================================================
; Description: Sends a start condition, writes the TWI address,
; control byte, and data byte, then issues a stop
; condition.
; -------------------------------------------------------------------
; Inputs: r22 - Control Byte (0x00: Command, 0x40: Data)
; r23 - Data Byte
; -------------------------------------------------------------------
; Instructions: AVR Instruction Set Manual
; 6.87 RCALL – Relative Call to Subroutine
; 6.95 LDI – Load Immediate
; 6.75 MOV – Copy Register
; 6.88 RET – Return from Subroutine
; 6.39 CLR - Clear Register
; 6.83 ORI – Logical OR with Immediate
; 6.117 STS – Store Direct to Data Space
; 6.70 LDS – Load Direct from Data Space
; 6.101 SBRS – Skip if Bit in Register is Set
; 6.90 RJMP – Relative Jump
; ===================================================================
TWI_write_byte:
rcall .TWI_start ; send start condition
ldi r24, (SSD1306_ADDR << 1) ; load SSD1306 addr w/ write bit
rcall .TWI_write ; write SSD1306 address
mov r24, r22 ; load control byte (Command/Data)
rcall .TWI_write ; write control byte
mov r24, r23 ; load data byte
rcall .TWI_write ; write data byte
rcall .TWI_stop ; send stop condition
ret ; return from subroutine
.TWI_start:
clr r16 ; clear r16 (initialize to 0)
ori r16, (1<

## License
[Apache License 2.0](https://github.com/mytechnotalent/ATmega328P_SSD1306_Driver/blob/main/LICENSE)