Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 86f6b391b733
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 082fdaf45056
Choose a head ref
  • 2 commits
  • 15 files changed
  • 1 contributor

Commits on Jan 4, 2017

  1. Copy the full SHA
    3dd9d54 View commit details
  2. Copy the full SHA
    082fdaf View commit details
4 changes: 0 additions & 4 deletions artiq/coredevice/exceptions.py
Original file line number Diff line number Diff line change
@@ -126,10 +126,6 @@ class DDSError(Exception):
incorrect.
"""

class I2CError(Exception):
"""Raised with a I2C transaction fails."""
artiq_builtin = True

class WatchdogExpired(Exception):
"""Raised when a watchdog expires."""

10 changes: 3 additions & 7 deletions artiq/coredevice/i2c.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from artiq.language.core import syscall, kernel
from artiq.language.types import TBool, TInt32, TNone
from artiq.coredevice.exceptions import I2CError


@syscall(flags={"nowrite"})
def i2c_init(busno: TInt32) -> TNone:
raise NotImplementedError("syscall not simulated")
class I2CError(Exception):
"""Raised with a I2C transaction fails."""
pass


@syscall(flags={"nounwind", "nowrite"})
@@ -48,7 +47,6 @@ def set(self, channel):
:param channel: channel number (0-7)
"""
i2c_init(self.busno)
i2c_start(self.busno)
try:
if not i2c_write(self.busno, self.address):
@@ -60,7 +58,6 @@ def set(self, channel):

@kernel
def readback(self):
i2c_init(self.busno)
i2c_start(self.busno)
r = 0
try:
@@ -84,7 +81,6 @@ def __init__(self, dmgr, busno=0, address=0x44, core_device="core"):

@kernel
def _write24(self, command, value):
i2c_init(self.busno)
i2c_start(self.busno)
try:
if not i2c_write(self.busno, self.address):
136 changes: 136 additions & 0 deletions artiq/firmware/libboard/i2c.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
use csr;
use clock;

fn half_period() { clock::spin_us(100) }
fn sda_bit(busno: u32) -> u8 { 1 << (2 * busno + 1) }
fn scl_bit(busno: u32) -> u8 { 1 << (2 * busno) }

fn sda_i(busno: u32) -> bool {
unsafe {
csr::i2c::in_read() & sda_bit(busno) != 0
}
}

fn sda_oe(busno: u32, oe: bool) {
unsafe {
let reg = csr::i2c::oe_read();
let reg = if oe { reg | sda_bit(busno) } else { reg & !sda_bit(busno) };
csr::i2c::oe_write(reg)
}
}

fn sda_o(busno: u32, o: bool) {
unsafe {
let reg = csr::i2c::out_read();
let reg = if o { reg | sda_bit(busno) } else { reg & !sda_bit(busno) };
csr::i2c::out_write(reg)
}
}

fn scl_oe(busno: u32, oe: bool) {
unsafe {
let reg = csr::i2c::oe_read();
let reg = if oe { reg | scl_bit(busno) } else { reg & !scl_bit(busno) };
csr::i2c::oe_write(reg)
}
}

fn scl_o(busno: u32, o: bool) {
unsafe {
let reg = csr::i2c::out_read();
let reg = if o { reg | scl_bit(busno) } else { reg & !scl_bit(busno) };
csr::i2c::out_write(reg)
}
}

pub fn init() {
for busno in 0..csr::CONFIG_I2C_BUS_COUNT {
// Set SCL as output, and high level
scl_o(busno, true);
scl_oe(busno, true);
// Prepare a zero level on SDA so that sda_oe pulls it down
sda_o(busno, false);
// Release SDA
sda_oe(busno, false);

// Check the I2C bus is ready
half_period();
half_period();
if !sda_i(busno) {
error!("SDA is stuck low on bus #{}", busno)
}
}
}

pub fn start(busno: u32) {
// Set SCL high then SDA low
scl_o(busno, true);
half_period();
sda_oe(busno, true);
half_period();
}

pub fn stop(busno: u32) {
// First, make sure SCL is low, so that the target releases the SDA line
scl_o(busno, false);
half_period();
// Set SCL high then SDA high
sda_oe(busno, true);
scl_o(busno, true);
half_period();
sda_oe(busno, false);
half_period();
}

pub fn write(busno: u32, data: u8) -> bool {
// MSB first
for bit in (0..8).rev() {
// Set SCL low and set our bit on SDA
scl_o(busno, false);
sda_oe(busno, data & (1 << bit) == 0);
half_period();
// Set SCL high ; data is shifted on the rising edge of SCL
scl_o(busno, true);
half_period();
}
// Check ack
// Set SCL low, then release SDA so that the I2C target can respond
scl_o(busno, false);
half_period();
sda_oe(busno, false);
// Set SCL high and check for ack
scl_o(busno, true);
half_period();
// returns true if acked (I2C target pulled SDA low)
!sda_i(busno)
}

pub fn read(busno: u32, ack: bool) -> u8 {
// Set SCL low first, otherwise setting SDA as input may cause a transition
// on SDA with SCL high which will be interpreted as START/STOP condition.
scl_o(busno, false);
half_period(); // make sure SCL has settled low
sda_oe(busno, false);

let mut data: u8 = 0;

// MSB first
for bit in (0..8).rev() {
scl_o(busno, false);
half_period();
// Set SCL high and shift data
scl_o(busno, true);
half_period();
if sda_i(busno) { data |= 1 << bit }
}
// Send ack
// Set SCL low and pull SDA low when acking
scl_o(busno, false);
if ack { sda_oe(busno, true) }
half_period();
// then set SCL high
scl_o(busno, true);
half_period();

data
}
2 changes: 2 additions & 0 deletions artiq/firmware/libboard/lib.rs
Original file line number Diff line number Diff line change
@@ -11,6 +11,8 @@ include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/csr.rs"));
pub mod spr;
pub mod irq;
pub mod clock;
#[cfg(has_i2c)]
pub mod i2c;
#[cfg(has_ad9516)]
#[allow(dead_code)]
mod ad9516_reg;
14 changes: 4 additions & 10 deletions artiq/firmware/libksupport/api.rs
Original file line number Diff line number Diff line change
@@ -106,14 +106,8 @@ static mut API: &'static [(&'static str, *const ())] = &[
api!(rtio_input_timestamp = ::rtio::input_timestamp),
api!(rtio_input_data = ::rtio::input_data),

#[cfg(has_i2c)]
api!(i2c_init = ::i2c::init),
#[cfg(has_i2c)]
api!(i2c_start = ::i2c::start),
#[cfg(has_i2c)]
api!(i2c_stop = ::i2c::stop),
#[cfg(has_i2c)]
api!(i2c_write = ::i2c::write),
#[cfg(has_i2c)]
api!(i2c_read = ::i2c::read),
api!(i2c_start = ::i2c_start),
api!(i2c_stop = ::i2c_stop),
api!(i2c_write = ::i2c_write),
api!(i2c_read = ::i2c_read),
];
176 changes: 0 additions & 176 deletions artiq/firmware/libksupport/i2c.rs

This file was deleted.

Loading