blob: 5cd44afbb2adc6555c57b52e9bb87c4f92607fa5 [file] [log] [blame]
#include "forth.h"
#include "i2c-bitbang.h"
void pinMode(uint8_t pin, uint8_t mode);
void digitalWrite(uint8_t pin, uint8_t val);
uint8_t digitalRead(uint8_t pin);
#define HIGH 1
#define LOW 0
#define INPUT 0
#define OUTPUT 1
#define INPUT_PULLUP 2
#define INPUT_PULLDOWN 3
#define OUTPUT_OPENDRAIN 4
volatile uint8_t i2c_sda_pin;
volatile uint8_t i2c_scl_pin;
#define SDA_LOW pinMode(i2c_sda_pin, OUTPUT_OPENDRAIN)
#define SDA_HIGH pinMode(i2c_sda_pin, INPUT)
#define SCL_LOW pinMode(i2c_scl_pin, OUTPUT_OPENDRAIN)
#define SCL_HIGH pinMode(i2c_scl_pin, INPUT)
// From teensy3/core_pins.h
#define F_CPU 96000000
void delayUs(uint32_t usec);
static void i2c_delay()
{
delayUs(5);
}
static void i2c_raise_scl(void)
{
i2c_delay();
SCL_HIGH;
i2c_delay();
}
static void i2c_master_setbit(uint8_t bit)
{
if (bit)
SDA_HIGH;
else
SDA_LOW;
i2c_raise_scl();
SCL_LOW;
}
static int i2c_master_getbit(void)
{
int result;
i2c_raise_scl();
result = digitalRead(i2c_sda_pin);
SCL_LOW;
return result;
}
static void i2c_master_writeByte(uint8_t value)
{
uint8_t mask;
for (mask=0x80; mask; mask >>= 1) {
i2c_master_setbit(value & mask);
}
}
static uint8_t i2c_master_readByte()
{
uint8_t mask;
uint8_t value = 0;
SDA_HIGH;
for (mask=0x80; mask; mask >>= 1) {
value = (value << 1) | i2c_master_getbit();
}
return value;
}
// void i2c_setup(cell sda, cell scl)
void i2c_setup(uint8_t sda, uint8_t scl)
{
i2c_sda_pin = sda;
i2c_scl_pin = scl;
SDA_HIGH;
SCL_HIGH;
digitalWrite(i2c_sda_pin, LOW);
digitalWrite(i2c_scl_pin, LOW);
}
void i2c_master_start()
{
SDA_LOW;
i2c_delay();
SCL_LOW;
}
void i2c_master_stop()
{
SDA_LOW;
i2c_raise_scl();
SDA_HIGH;
i2c_delay();
}
// Returns nonzero if error
cell i2c_send(cell byte)
{
i2c_master_writeByte((uint8_t)byte);
SDA_HIGH;
uint8_t r = i2c_master_getbit();
if (r)
i2c_master_stop();
return r;
}
cell i2c_recv(cell nack)
{
uint8_t r = i2c_master_readByte();
i2c_master_setbit(nack);
if (nack)
i2c_master_stop();
return r;
}
// Start + slave address + reg#
cell i2c_start_write(cell slave, cell reg)
{
i2c_master_start();
if (i2c_send(slave<<1))
return -1;
if (i2c_send(reg))
return -1;
return 0;
}
cell i2c_start_read(cell slave, cell stop)
{
if (stop)
i2c_master_stop();
else {
SDA_HIGH;
i2c_delay;
SCL_HIGH;
i2c_delay;
}
i2c_master_start();
return i2c_send((slave<<1) | 1);
}
cell i2c_rb(cell stop, cell slave, cell reg)
{
if (i2c_start_write(slave, reg))
return -1;
if (i2c_start_read(slave, stop))
return -1;
return i2c_recv(1);
}
cell i2c_wb(cell slave, cell reg, cell value)
{
if (i2c_start_write(slave, reg))
return -1;
if (i2c_send(value))
return -1;
i2c_master_stop();
return 0;
}
cell i2c_be_rw(cell stop, cell slave, cell reg)
{
if (i2c_start_write(slave, reg))
return -1;
if (i2c_start_read(slave, stop))
return -1;
cell val = i2c_recv(0);
val = (val<<8) + i2c_recv(1);
return val;
}
cell i2c_le_rw(cell stop, cell slave, cell reg)
{
if (i2c_start_write(slave, reg))
return -1;
if (i2c_start_read(slave, stop))
return -1;
cell val = i2c_recv(0);
val += i2c_recv(1)<<8;
return val;
}
cell i2c_be_ww(cell slave, cell reg, cell value)
{
if (i2c_start_write(slave, reg))
return -1;
if (i2c_send(value>>8))
return -1;
if (i2c_send(value&0xff))
return -1;
i2c_master_stop();
return 0;
}
cell i2c_le_ww(cell slave, cell reg, cell value)
{
if (i2c_start_write(slave, reg))
return -1;
if (i2c_send(value&0xff))
return -1;
if (i2c_send(value>>8))
return -1;
i2c_master_stop();
return 0;
}