Skip to content

Commit

Permalink
avr: work in progress on i2c implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Ron Evans <ron@hybridgroup.com>
  • Loading branch information
deadprogram committed Sep 22, 2018
1 parent dd5b5a3 commit f3c8e28
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 2 deletions.
67 changes: 67 additions & 0 deletions src/examples/i2clcd/i2clcd.go
@@ -0,0 +1,67 @@
// Connects to an jhd1313m1 I2C LCD display.
package main

import (
"machine"
"time"
)

const (
REG_RED = 0x04
REG_GREEN = 0x03
REG_BLUE = 0x02

LCD_CLEARDISPLAY = 0x01
LCD_RETURNHOME = 0x02
LCD_ENTRYMODESET = 0x04
LCD_DISPLAYCONTROL = 0x08
LCD_CURSORSHIFT = 0x10
LCD_FUNCTIONSET = 0x20
LCD_SETCGRAMADDR = 0x40
LCD_SETDDRAMADDR = 0x80
LCD_ENTRYRIGHT = 0x00
LCD_ENTRYLEFT = 0x02
LCD_ENTRYSHIFTINCREMENT = 0x01
LCD_ENTRYSHIFTDECREMENT = 0x00
LCD_DISPLAYON = 0x04
LCD_DISPLAYOFF = 0x00
LCD_CURSORON = 0x02
LCD_CURSOROFF = 0x00
LCD_BLINKON = 0x01
LCD_BLINKOFF = 0x00
LCD_DISPLAYMOVE = 0x08
LCD_CURSORMOVE = 0x00
LCD_MOVERIGHT = 0x04
LCD_MOVELEFT = 0x00
LCD_2LINE = 0x08
LCD_CMD = 0x80
LCD_DATA = 0x40

LCD_2NDLINEOFFSET = 0x40
)

func main() {
machine.I2CInit()
time.Sleep(100 * time.Microsecond)

// Init display
initBytes := []byte{LCD_CMD, LCD_FUNCTIONSET | LCD_2LINE}
machine.I2CWriteTo(0x3e, initBytes)

// uncommmenting this next line will cause compile to fail
// time.Sleep(450 * time.Microsecond)
// machine.I2CWriteTo(0x3e, initBytes)
// time.Sleep(150 * time.Microsecond)
// machine.I2CWriteTo(0x3e, initBytes)

// // Turn on display
// machine.I2CWriteTo(0x3e, []byte{LCD_CMD, LCD_DISPLAYCONTROL | LCD_DISPLAYON})
// time.Sleep(100 * time.Microsecond)

// // Clear display
// machine.I2CWriteTo(0x3e, []byte{LCD_CLEARDISPLAY})

for {

}
}
99 changes: 97 additions & 2 deletions src/machine/machine_avr.go
Expand Up @@ -131,8 +131,8 @@ const (
ADC1 = 1
ADC2 = 2
ADC3 = 3
ADC4 = 4
ADC5 = 5
ADC4 = 4 // Used by TWI for SDA
ADC5 = 5 // Used by TWI for SCL
)

// InitADC initializes the registers needed for ADC.
Expand Down Expand Up @@ -170,3 +170,98 @@ func (a ADC) Get() uint16 {
high := uint16(*avr.ADCH)
return uint16(low) | uint16(high<<8)
}

// I2C on the Arduino

const (
SDA = 18
SCL = 19
)

// I2CInit initializes the I2C interface.
func I2CInit() {
// Activate internal pullups for twi.
sda := GPIO{SDA}
sda.Configure(GPIOConfig{Mode: GPIO_OUTPUT})
sda.High()
scl := GPIO{SCL}
scl.Configure(GPIOConfig{Mode: GPIO_OUTPUT})
scl.High()

// Initialize twi prescaler and bit rate.
*avr.TWSR |= (avr.TWSR_TWPS0 | avr.TWSR_TWPS1)

// twi bit rate formula from atmega128 manual pg. 204:
// SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR))
// NOTE: TWBR should be 10 or higher for master mode.
// It is 72 for a 16mhz board with 100kHz TWI
*avr.TWBR = avr.RegValue(72)

// Enable twi module, acks, and twi interrupt.
*avr.TWCR = (avr.TWCR_TWEN | avr.TWCR_TWIE | avr.TWCR_TWEA)
}

// I2CStart starts a communication session.
func I2CStart() {
// Clear TWI interrupt flag, put start condition on SDA, and enable TWI.
*avr.TWCR = (avr.TWCR_TWINT | avr.TWCR_TWSTA | avr.TWCR_TWEN)

// Wait till start condition is transmitted.
for ok := true; ok; ok = (*avr.TWCR & avr.TWCR_TWINT) == 0 {
}
}

// I2CStop ends a communication session.
func I2CStop() {
// Send stop condition.
*avr.TWCR = (avr.TWCR_TWEN | avr.TWCR_TWINT | avr.TWCR_TWSTO)

// Wait for stop condition to be executed on bus.
for ok := true; ok; ok = (*avr.TWCR & avr.TWCR_TWSTO) > 0 {
}
}

// I2CWriteTo writes a slice of data bytes to a peripheral with a specific address.
func I2CWriteTo(address uint8, data []byte) {
I2CStart()

// Write 7-bit shifted peripheral address plus write flag
I2CWriteByte(address<<1 + 1)

for _, v := range data {
I2CWriteByte(v)
}

I2CStop()
}

// I2CReadFrom reads a slice of data bytes from a peripheral with a specific address.
func I2CReadFrom(address uint8, data []byte) {
I2CStart()

// Write 7-bit shifted peripheral address
I2CWriteByte(address << 7)

// TODO: handle read

I2CStop()
}

// I2CWriteByte writes a single byte to the I2C bus.
func I2CWriteByte(data byte) {
// Write data to register.
*avr.TWDR = avr.RegValue(data)

// Clear TWI interrupt flag and enable TWI.
*avr.TWCR = (avr.TWCR_TWEN | avr.TWCR_TWINT)

// Wait till data is transmitted.
for ok := true; ok; ok = (*avr.TWCR & avr.TWCR_TWINT) == 0 {
}
}

// I2CReadByte reads a single byte from the I2C bus.
func I2CReadByte() byte {
// TODO: implement
return 0x00
}

0 comments on commit f3c8e28

Please sign in to comment.