Merge pull request #2814 from wavexx/MK3_PAT9125_I2C

Use hardware TWI for the PAT9125 (optical) filament sensor
This commit is contained in:
DRracer 2021-02-02 09:15:35 +01:00 committed by GitHub
commit 2b81abb24c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 277 additions and 57 deletions

View file

@ -90,18 +90,13 @@
#include "la10compat.h"
#endif
#ifdef SWSPI
#include "swspi.h"
#endif //SWSPI
#include "spi.h"
#ifdef SWI2C
#include "swi2c.h"
#endif //SWI2C
#ifdef FILAMENT_SENSOR
#include "fsensor.h"
#ifdef IR_SENSOR
#include "pat9125.h" // for pat9125_probe
#endif
#endif //FILAMENT_SENSOR
#ifdef TMC2130
@ -922,9 +917,7 @@ static void check_if_fw_is_on_right_printer(){
#ifdef FILAMENT_SENSOR
if((PRINTER_TYPE == PRINTER_MK3) || (PRINTER_TYPE == PRINTER_MK3S)){
#ifdef IR_SENSOR
swi2c_init();
const uint8_t pat9125_detected = swi2c_readByte_A8(PAT9125_I2C_ADDR,0x00,NULL);
if (pat9125_detected){
if (pat9125_probe()){
lcd_show_fullscreen_message_and_wait_P(_i("MK3S firmware detected on MK3 printer"));}////c=20 r=3
#endif //IR_SENSOR

View file

@ -37,10 +37,6 @@ struct pin_map_t {
|| defined(__AVR_ATmega2560__)
// Mega
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 20; // D1
uint8_t const SCL_PIN = 21; // D0
#undef MOSI_PIN
#undef MISO_PIN
// SPI port
@ -365,4 +361,4 @@ static inline __attribute__((always_inline))
#endif // Sd2PinMap_h
#endif
#endif

View file

@ -23,7 +23,6 @@
#define ADC_CALLBACK adc_ready //callback function ()
//SWI2C configuration
#define SWI2C
//#define SWI2C_SDA 20 //SDA on P3
//#define SWI2C_SCL 21 //SCL on P3
#define SWI2C_A8
@ -31,7 +30,13 @@
#define SWI2C_TMO 2048 //2048 cycles timeout
//PAT9125 configuration
#define PAT9125_SWI2C
//#define PAT9125_SWSPI // software SPI mode (incomplete)
#ifdef SWI2C_SCL
#define PAT9125_SWI2C // software I2C mode
#else
#define PAT9125_I2C // hardware I2C mode
#endif
#define PAT9125_I2C_ADDR 0x75 //ID=LO
//#define PAT9125_I2C_ADDR 0x79 //ID=HI
//#define PAT9125_I2C_ADDR 0x73 //ID=NC

View file

@ -9,6 +9,7 @@
#include <avr/io.h>
#include "macros.h"
/*
magic I/O routines
now you can simply SET_OUTPUT(STEP); WRITE(STEP, 1); WRITE(STEP, 0);

View file

@ -26,12 +26,15 @@
#define PAT9125_BANK_SELECTION 0x7f
#ifdef PAT9125_SWSPI
#if defined(PAT9125_SWSPI)
#include "swspi.h"
#endif //PAT9125_SWSPI
#ifdef PAT9125_SWI2C
#elif defined(PAT9125_SWI2C)
#include "swi2c.h"
#endif //PAT9125_SWI2C
#elif defined(PAT9125_I2C)
#include "twi.h"
#else
#error unknown PAT9125 communication method
#endif
uint8_t pat9125_PID1 = 0;
@ -103,14 +106,31 @@ extern FILE _uartout;
#define uartout (&_uartout)
uint8_t pat9125_probe()
{
#if defined(PAT9125_SWSPI)
swspi_init();
#error not implemented
#elif defined(PAT9125_SWI2C)
swi2c_init();
return swi2c_readByte_A8(PAT9125_I2C_ADDR,0x00,NULL);
#elif defined(PAT9125_I2C)
twi_init();
#ifdef IR_SENSOR
// NOTE: this is called from the MK3S variant, so it should be kept minimal
uint8_t data;
return (twi_r8(PAT9125_I2C_ADDR,PAT9125_PID1,&data) == 0);
#else
return (pat9125_rd_reg(PAT9125_PID1) != 0);
#endif
#endif
}
uint8_t pat9125_init(void)
{
#ifdef PAT9125_SWSPI
swspi_init();
#endif //PAT9125_SWSPI
#ifdef PAT9125_SWI2C
swi2c_init();
#endif //PAT9125_SWI2C
if (!pat9125_probe())
return 0;
// Verify that the sensor responds with its correct product ID.
pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
@ -234,39 +254,46 @@ uint8_t pat9125_update_bs(void)
uint8_t pat9125_rd_reg(uint8_t addr)
{
uint8_t data = 0;
#ifdef PAT9125_SWSPI
#if defined(PAT9125_SWSPI)
swspi_start();
swspi_tx(addr & 0x7f);
data = swspi_rx();
swspi_stop();
#endif //PAT9125_SWSPI
#ifdef PAT9125_SWI2C
#elif defined(PAT9125_SWI2C)
if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
{
pat9125_PID1 = 0xff;
pat9125_PID2 = 0xff;
return 0;
}
#endif //PAT9125_SWI2C
goto error;
#elif defined(PAT9125_I2C)
if (twi_r8(PAT9125_I2C_ADDR,addr,&data))
goto error;
#endif
return data;
error:
pat9125_PID1 = 0xff;
pat9125_PID2 = 0xff;
return 0;
}
void pat9125_wr_reg(uint8_t addr, uint8_t data)
{
#ifdef PAT9125_SWSPI
#if defined(PAT9125_SWSPI)
swspi_start();
swspi_tx(addr | 0x80);
swspi_tx(data);
swspi_stop();
#endif //PAT9125_SWSPI
#ifdef PAT9125_SWI2C
#elif defined(PAT9125_SWI2C)
if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
{
pat9125_PID1 = 0xff;
pat9125_PID2 = 0xff;
return;
}
#endif //PAT9125_SWI2C
goto error;
#elif defined(PAT9125_I2C)
if (twi_w8(PAT9125_I2C_ADDR,addr,data))
goto error;
#endif
return;
error:
pat9125_PID1 = 0xff;
pat9125_PID2 = 0xff;
return;
}
uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data)

View file

@ -18,6 +18,7 @@ extern int16_t pat9125_y;
extern uint8_t pat9125_b;
extern uint8_t pat9125_s;
extern uint8_t pat9125_probe(void); // Return non-zero if PAT9125 can be trivially detected
extern uint8_t pat9125_init(void);
extern uint8_t pat9125_update(void); // update all sensor data
extern uint8_t pat9125_update_y(void); // update _y only

View file

@ -25,6 +25,11 @@
#error Unknown MOTHERBOARD value in configuration.h
#endif
#if !defined(SDA_PIN) && (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
#define SDA_PIN 20
#define SCL_PIN 21
#endif
//List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those!
#define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN,
#if EXTRUDERS > 1

View file

@ -18,12 +18,6 @@
#define W25X20CL // external 256kB flash
#define BOOTAPP // bootloader support
#define SWI2C_SDA 20 //SDA on P3
#define SWI2C_SCL 21 //SCL on P3
#define X_TMC2130_CS 41
#define X_TMC2130_DIAG 64 // !!! changed from 40 (EINY03)
#define X_STEP_PIN 37

View file

@ -11,9 +11,6 @@
#define PINDA_THERMISTOR
#define SWI2C_SDA 20 //SDA on P3
#define SWI2C_SCL 21 //SCL on P3
#ifdef MICROMETER_LOGGING
#define D_DATACLOCK 24 //Y_MAX (green)
#define D_DATA 30 //X_MAX (blue)

View file

@ -8,6 +8,7 @@
#include "pins.h"
#include "fastio.h"
#ifdef SWI2C_SCL
#define SWI2C_RMSK 0x01 //read mask (bit0 = 1)
#define SWI2C_WMSK 0x00 //write mask (bit0 = 0)
@ -187,3 +188,5 @@ uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyt
}
#endif //SWI2C_A16
#endif //SWI2C_SCL

View file

@ -7,8 +7,6 @@
#ifdef SYSTEM_TIMER_2
#include <avr/io.h>
#include <avr/interrupt.h>
#include "pins.h"
#include "fastio.h"
#include "macros.h"

137
Firmware/twi.c Normal file
View file

@ -0,0 +1,137 @@
/*
twi.c - Stripped-down TWI/I2C library
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts
*/
#include <math.h>
#include "config.h"
#include "fastio.h"
#include "twi.h"
void twi_init(void)
{
// activate internal pullups for twi.
WRITE(SDA_PIN, 1);
WRITE(SCL_PIN, 1);
// initialize twi prescaler and bit rate
TWSR &= ~(_BV(TWPS0) | _BV(TWPS1));
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
/* 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 Wiring board with 100kHz TWI */
}
void twi_disable(void)
{
// deactivate internal pullups for twi.
WRITE(SDA_PIN, 0);
WRITE(SCL_PIN, 0);
}
static void twi_stop()
{
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO);
}
static uint8_t twi_wait(uint8_t status)
{
while(!(TWCR & _BV(TWINT)));
if(TW_STATUS != status)
{
twi_stop();
return 1;
}
return 0;
}
static uint8_t twi_start(uint8_t address, uint8_t reg)
{
// send start condition
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA);
if(twi_wait(TW_START))
return 1;
// send address
TWDR = TW_WRITE | (address << 1);
TWCR = _BV(TWEN) | _BV(TWINT);
if(twi_wait(TW_MT_SLA_ACK))
return 2;
// send register
TWDR = reg;
TWCR = _BV(TWEN) | _BV(TWINT);
if(twi_wait(TW_MT_DATA_ACK))
return 3;
return 0;
}
uint8_t twi_r8(uint8_t address, uint8_t reg, uint8_t* data)
{
if(twi_start(address, reg))
return 1;
// repeat start
TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA);
if(twi_wait(TW_REP_START))
return 2;
// start receiving
TWDR = TW_READ | (address << 1);
TWCR = _BV(TWEN) | _BV(TWINT);
if(twi_wait(TW_MR_SLA_ACK))
return 3;
// receive data
TWCR = _BV(TWEN) | _BV(TWINT);
if(twi_wait(TW_MR_DATA_NACK))
return 4;
*data = TWDR;
// send stop
twi_stop();
return 0;
}
uint8_t twi_w8(uint8_t address, uint8_t reg, uint8_t data)
{
if(twi_start(address, reg))
return 1;
// send data
TWDR = data;
TWCR = _BV(TWEN) | _BV(TWINT);
if(twi_wait(TW_MT_DATA_ACK))
return 2;
// send stop
twi_stop();
return 0;
}

63
Firmware/twi.h Normal file
View file

@ -0,0 +1,63 @@
/*
twi.h - Stripped-down TWI/I2C library
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <inttypes.h>
#include <compat/twi.h>
#ifndef TWI_FREQ
#define TWI_FREQ 400000L
#endif
/*
* Function twi_init
* Desc readys twi pins and sets twi bitrate
* Input none
* Output none
*/
void twi_init(void);
/*
* Function twi_disable
* Desc disables twi pins
* Input none
* Output none
*/
void twi_disable(void);
/*
* Function twi_r8
* Desc read a single byte from a device
* Input address: 7bit i2c device address
* reg: register address
* data: pointer to byte for result
* Output 0 on success
*/
uint8_t twi_r8(uint8_t address, uint8_t reg, uint8_t* data);
/*
* Function twi_w8
* Desc write a single byte from a device
* Input address: 7bit i2c device address
* reg: register address
* data: byte to write
* Output 0 on success
*/
uint8_t twi_w8(uint8_t address, uint8_t reg, uint8_t data);