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. Verified

    This commit was signed with the committer’s verified signature.
    makenowjust Hiroya Fujinami
    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