Added i2c bit-banging. Broken, I can't be bothered to fix without a signal analyser

main-solar-only
Richard Meadows 2015-12-24 18:12:02 +00:00
rodzic 9ee4f34a35
commit c7b1c5278c
5 zmienionych plików z 287 dodań i 11 usunięć

Wyświetl plik

@ -0,0 +1,34 @@
/*
* i2c bit-bang
* Copyright (C) 2015 Richard Meadows <richardeoin>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef I2C_BB_H
#define I2C_BB_H
#include "samd20.h"
void i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length);
void i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length);
void i2c_bb_init(void);
#endif /* I2C_BB_H */

Wyświetl plik

@ -0,0 +1,42 @@
/*
* MS5607
* Copyright (C) 2015 Richard Meadows <richardeoin>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MS5607_H
#define MS5607_H
#include "samd20.h"
/**
* Barometer data structure
*/
struct barometer {
double temperature;
double pressure;
int valid; // 1 = valid, 0 = invalid
};
struct barometer* get_barometer(void);
void ms5607_init(void);
#endif /* MS5607_H */

Wyświetl plik

@ -0,0 +1,198 @@
/*
* i2c bit-bang
* Copyright (C) 2015 Richard Meadows <richardeoin>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "samd20.h"
#include "hw_config.h"
#include "system/port.h"
#define SDA I2C_SERCOM_SDA_PIN
#define SCL I2C_SERCOM_SCL_PIN
/**
* Helper functions for pin access
*/
static inline void i2c_bb_claim_pin(uint32_t pin, uint8_t value)
{
port_pin_set_config(pin,
SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK, /* Direction */
SYSTEM_PINMUX_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
port_pin_set_output_level(pin, value);
}
static inline void i2c_bb_release_pin(uint32_t pin)
{
port_pin_set_config(pin,
SYSTEM_PINMUX_PIN_DIR_INPUT, /* Direction */
SYSTEM_PINMUX_PIN_PULL_NONE, /* Pull */
false); /* Powersave */
}
#define i2c_bb_write_pin port_pin_set_output_level
#define i2c_bb_read_pin port_pin_get_input_level
/**
* i2c start
*/
void i2c_bb_start(void)
{
i2c_bb_claim_pin(SDA, 1); /* force pins high */
i2c_bb_claim_pin(SCL, 1);
i2c_bb_write_pin(SDA, 0); /* set SDA low */
i2c_bb_write_pin(SCL, 0); /* then SCL */
i2c_bb_write_pin(SDA, 1); /* return SDA high */
}
/**
* i2c stop
*/
void i2c_bb_stop(void)
{
i2c_bb_write_pin(SCL, 0); /* set both lines low */
i2c_bb_write_pin(SDA, 0);
i2c_bb_release_pin(SCL); /* release SCL */
i2c_bb_release_pin(SDA); /* then SDA */
}
/**
* writes a single i2c byte
*/
void i2c_bb_put_byte(uint8_t b)
{
uint8_t bit;
for (uint8_t i = 0; i < 8; i++) {
bit = (b & 0x80) ? 1:0; /* get msb */
b = b << 1;
if (i == 0) {
i2c_bb_claim_pin(SDA, bit);
} else {
i2c_bb_write_pin(SDA, bit);
}
i2c_bb_write_pin(SCL, 1); /* clock out */
if ((i == 7) && bit) { i2c_bb_release_pin(SDA); } /* release early if high */
i2c_bb_write_pin(SCL, 0);
}
i2c_bb_release_pin(SDA); /* release SDA pin */
}
uint8_t i2c_bb_get_byte(void)
{
uint8_t bit, b = 0;
i2c_bb_release_pin(SDA); /* release SDA */
for (uint8_t i = 0; i < 8; i++) {
i2c_bb_write_pin(SCL, 1); /* clock in */
bit = i2c_bb_read_pin(SDA);
i2c_bb_write_pin(SCL, 0);
b |= (bit?1:0); /* write msb first */
b = b << 1;
}
return b;
}
/**
* Issues i2c acknoledge
*/
void i2c_bb_ack(void)
{
i2c_bb_claim_pin(SDA, 0);
i2c_bb_write_pin(SCL, 1); /* clock out */
i2c_bb_write_pin(SCL, 0);
i2c_bb_write_pin(SDA, 1);
}
/**
* Waits to receive a slave ack. SDA is already released
*/
void i2c_bb_get_ack(void)
{
i2c_bb_write_pin(SCL, 1);
// while (i2c_bb_read_pin(SDA)); /* wait for SDA=0 */
i2c_bb_write_pin(SCL, 0);
}
/**
* I2C Read.
*
* address is the full read address like 0xEF
*/
void i2c_bb_read(uint8_t address, uint8_t* data, uint8_t data_length)
{
address |= 1; /* set read flag */
i2c_bb_start(); /* start. claim both */
i2c_bb_put_byte(address); /* address. claim and relase SDA */
i2c_bb_get_ack(); /* slave acks */
for (uint8_t n = 0; n < data_length; n++) {
data[n] = i2c_bb_get_byte(); /* read byte. release SDA */
if (n+1 < data_length) { /* if not last byte */
i2c_bb_ack(); /* ack. claim SDA */
}
}
i2c_bb_stop(); /* stop. release both */
}
/**
* I2C Write.
*
* address is the full write address like 0xEE
*/
void i2c_bb_write(uint8_t address, uint8_t* data, uint8_t data_length)
{
address &= ~1; /* clear read flag */
i2c_bb_start(); /* start. claim both */
i2c_bb_put_byte(address); /* address. claim and release SDA */
i2c_bb_get_ack(); /* slave acks */
for (uint8_t n = 0; n < data_length; n++) {
i2c_bb_put_byte(data[n]); /* data. claim and release SDA */
i2c_bb_get_ack(); /* slave acks */
}
i2c_bb_claim_pin(SDA, 0); /* claim SDA again */
i2c_bb_stop(); /* stop */
}
void i2c_bb_init(void)
{
i2c_bb_claim_pin(SDA, 1);
i2c_bb_claim_pin(SCL, 0);
i2c_bb_stop(); /* stop. release both */
}

Wyświetl plik

@ -28,7 +28,7 @@
#include "system/port.h"
#include "system/events.h"
#include "system/extint.h"
#include "sercom/i2c.h"
#include "i2c_bb.h"
#include "gps.h"
#include "si_trx.h"
#include "watchdog.h"
@ -119,7 +119,8 @@ void init(enum init_type init_t)
*/
/* i2c */
i2c_init(I2C_SERCOM, I2C_SERCOM_SDA_PINMUX, I2C_SERCOM_SCL_PINMUX);
//i2c_init(I2C_SERCOM, I2C_SERCOM_SDA_PINMUX, I2C_SERCOM_SCL_PINMUX);
i2c_bb_init();
kick_the_watchdog();

Wyświetl plik

@ -31,7 +31,8 @@
#if BAROMETER_TYPE_MS5607
#include "barometer.h"
#include "sercom/i2c.h"
//#include "sercom/i2c.h"
#include "i2c_bb.h"
#define MS5607_ADDRESS 0xEE
@ -100,7 +101,7 @@ void command(uint8_t command) {
buffer[0] = command;
/* Write command */
i2c_master_write(MS5607_ADDRESS, buffer, 1);
i2c_bb_write(MS5607_ADDRESS, buffer, 1);
}
/**
* Reads an 8-bit value
@ -110,10 +111,10 @@ uint8_t read_8(uint8_t command) {
buffer[0] = command;
/* Write command */
i2c_master_write(MS5607_ADDRESS, buffer, 1);
i2c_bb_write(MS5607_ADDRESS, buffer, 1);
/* Read it */
i2c_master_read(MS5607_ADDRESS, buffer, 1);
i2c_bb_read(MS5607_ADDRESS, buffer, 1);
return buffer[0];
}
@ -125,10 +126,10 @@ uint16_t read_16(uint8_t command) {
buffer[0] = command;
/* Write command */
i2c_master_write(MS5607_ADDRESS, buffer, 1);
i2c_bb_write(MS5607_ADDRESS, buffer, 1);
/* Read it */
i2c_master_read(MS5607_ADDRESS, buffer, 2);
i2c_bb_read(MS5607_ADDRESS, buffer, 2);
return (buffer[0] << 8) | buffer[1];
}
@ -140,10 +141,10 @@ uint32_t read_24(uint8_t command) {
buffer[0] = command;
/* Write command */
i2c_master_write(MS5607_ADDRESS, buffer, 1);
i2c_bb_write(MS5607_ADDRESS, buffer, 1);
/* Read it */
i2c_master_read(MS5607_ADDRESS, buffer, 3);
i2c_bb_read(MS5607_ADDRESS, buffer, 3);
return (buffer[0] << 16) | (buffer[1] << 8) | buffer[2];
}
@ -298,7 +299,7 @@ struct barometer* get_barometer(void)
}
/**
* Assume twi_master_init has already been called
* Assume i2c_bb_init has already been called
*/
void barometer_init(void)
{