From 3f0e7f25f16423858fd11f1660a599c353ab9e70 Mon Sep 17 00:00:00 2001 From: Werner Johansson Date: Fri, 19 Dec 2014 17:49:24 -0800 Subject: [PATCH 1/4] Initial stab at supporting the MAX31855/SC18IS602B combo The intent is that this should behave the exakt same way as the 1-wire version --- src/main.c | 2 + src/max31855.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++ src/max31855.h | 9 ++++ src/reflow.c | 12 ++++- src/sc18is602b.c | 54 ++++++++++++++++++++++ src/sc18is602b.h | 32 +++++++++++++ src/sched.h | 1 + 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 src/max31855.c create mode 100644 src/max31855.h create mode 100644 src/sc18is602b.c create mode 100644 src/sc18is602b.h diff --git a/src/main.c b/src/main.c index c2c8810..86d6fc1 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ #include "buzzer.h" #include "nvstorage.h" #include "version.h" +#include "max31855.h" extern uint8_t logobmp[]; extern uint8_t stopbmp[]; @@ -170,6 +171,7 @@ int main(void) { ADC_Init(); RTC_Init(); OneWire_Init(); + SPI_TC_Init(); Reflow_Init(); Sched_SetWorkfunc( MAIN_WORK, Main_Work ); diff --git a/src/max31855.c b/src/max31855.c new file mode 100644 index 0000000..d48ead1 --- /dev/null +++ b/src/max31855.c @@ -0,0 +1,117 @@ +/* + * max31855.c - SPI TC interface handling for T-962 reflow controller + * + * Copyright (C) 2014 Werner Johansson, wj@unifiedengineering.se + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "sc18is602b.h" +#include "sched.h" + +#define MAX_SPI_DEVICES (4) +int16_t spidevreadout[MAX_SPI_DEVICES]; // Keeps last readout from each device +int16_t spiextrareadout[MAX_SPI_DEVICES]; // Keeps last readout from each device +int numspidevices = 0; + +static int32_t SPI_TC_Work( void ) { + int32_t retval = TICKS_MS(100); + + for( int i = 0; i < numspidevices; i++ ) { + SPIxfer_t xfer; + xfer.ssmask = 1<= 0 ) { // Only continue of we find the I2C to SPI bridge chip + printf("\nProbing for MAX31855 devices..."); + + SPI_TC_Work(); // Run one iteration to update all data + + for( int i = 0; i < MAX_SPI_DEVICES; i++ ) { + if( (spidevreadout[i] == -1 && spiextrareadout[i] == -1) || + (spidevreadout[i] == 0 && spiextrareadout[i] == 0) ) { + //printf(" Unknown/Invalid/Absent device"); + } else { + printf("\nSS%x: [SPI Thermocouple interface]", i); + numspidevices = i + 1; // A bit of a hack as it assumes all earlier devices are present + } + } + + if( numspidevices ) { + Sched_SetState( SPI_TC_WORK, 2, 0 ); // Enable SPI TC task if there's at least one device + } else { + printf(" No devices found!"); + } + } + return numspidevices; +} + +int SPI_IsTCPresent(uint8_t tcid) { + if(tcid < numspidevices) { + if( !(spidevreadout[tcid] & 0x01) ) return 1; // A faulty/not connected TC will not be flagged as present + } + return 0; +} + +float SPI_GetTCReading(uint8_t tcid) { + float retval = 0.0f; // Report 0C for missing sensors + if(tcid < numspidevices) { + if(spidevreadout[tcid] & 0x01) { // Fault detected + retval = 999.0f; // Invalid + } else { + retval=(float)(spidevreadout[tcid] & 0xfffc); // Mask reserved bit + retval/=16; + //printf(" (%x=%.1f C)",tcid,retval); + } + } + return retval; +} + +float SPI_GetTCColdReading(uint8_t tcid) { + float retval = 0.0f; // Report 0C for missing sensors + if(tcid < numspidevices) { + if(spiextrareadout[tcid] & 0x07) { // Any fault detected + retval = 999.0f; // Invalid + } else { + retval=(float)(spiextrareadout[tcid] & 0xfff0); // Mask reserved/fault bits + retval/=256; + //printf(" (%x=%.1f C)",tcid,retval); + } + } + return retval; +} diff --git a/src/max31855.h b/src/max31855.h new file mode 100644 index 0000000..5119b47 --- /dev/null +++ b/src/max31855.h @@ -0,0 +1,9 @@ +#ifndef MAX31855_H_ +#define MAX31855_H_ + +uint32_t SPI_TC_Init( void ); +int SPI_IsTCPresent(uint8_t tcid); +float SPI_GetTCReading(uint8_t tcid); +float SPI_GetTCColdReading(uint8_t tcid); + +#endif /* MAX31855_H_ */ diff --git a/src/reflow.c b/src/reflow.c index 95428e9..52ea3d4 100644 --- a/src/reflow.c +++ b/src/reflow.c @@ -31,6 +31,7 @@ #include "onewire.h" #include "adc.h" #include "nvstorage.h" +#include "max31855.h" float adcgainadj[2]; // Gain adjust, this may have to be calibrated per device if factory trimmer adjustments are off float adcoffsetadj[2]; // Offset adjust, this will definitely have to be calibrated per device @@ -119,7 +120,16 @@ static int32_t Reflow_Work( void ) { tempvalid |= (1<1) { + temperature[i] = tctemp[i]; + tempvalid |= (1<. + */ + +#include +#include +#include +#include +#include "i2c.h" +#include "sc18is602b.h" + +#define SCADDR (0x28<<1) + +int32_t SC18IS602B_Init( SPIclk_t clk, SPImode_t mode, SPIorder_t order ) { + uint8_t function[2]; + int32_t retval; + printf("\n%s ",__FUNCTION__); + function[0] = 0xf0; + function[1] = clk | mode | order; + retval = I2C_Xfer(SCADDR, function, sizeof(function), 1); // Attempt to initialize I2C to SPI bridge + if( retval == 0 ) { + printf( "- Done"); + } else { + printf( "- No chip found"); + } + return retval; +} + +int32_t SC18IS602B_SPI_Xfer( SPIxfer_t* item ) { + int32_t retval; + if( item->len > (sizeof(SPIxfer_t) - 2) ) return -1; // Invalid length + retval = I2C_Xfer(SCADDR, (uint8_t*)item, item->len + 1, 1); // Initialize transfer, ssmask + data + if( retval == 0 ) { + do { + retval = I2C_Xfer(SCADDR + 1, (uint8_t*)item->data, item->len, 1); // Initialize read transfer, data only + } while( retval != 0 ); // Wait for chip to be done with transaction + } + return retval; +} diff --git a/src/sc18is602b.h b/src/sc18is602b.h new file mode 100644 index 0000000..348872f --- /dev/null +++ b/src/sc18is602b.h @@ -0,0 +1,32 @@ +#ifndef SC18IS602B_H_ +#define SC18IS602B_H_ + +typedef enum eSPIclk { + SPICLK_1843KHZ=0, + SPICLK_461KHZ=1, + SPICLK_115KHZ=2, + SPICLK_58KHZ=3, +} SPIclk_t; + +typedef enum eSPImode { + SPIMODE_0=(0<<2), + SPIMODE_1=(1<<2), + SPIMODE_2=(2<<2), + SPIMODE_3=(3<<2), +} SPImode_t; + +typedef enum eSPIorder { + SPIORDER_MSBFIRST=(0<<5), + SPIORDER_LSBFIRST=(1<<5), +} SPIorder_t; + +typedef struct __attribute__ ((__packed__)) { + uint8_t ssmask; + uint8_t data[16]; // Max 16 bytes at the moment + uint8_t len; +} SPIxfer_t; + +int32_t SC18IS602B_Init( SPIclk_t clk, SPImode_t mode, SPIorder_t order ); +int32_t SC18IS602B_SPI_Xfer( SPIxfer_t* item ); + +#endif /* SC18IS602B_H_ */ diff --git a/src/sched.h b/src/sched.h index 19c93ef..d7fb987 100644 --- a/src/sched.h +++ b/src/sched.h @@ -23,6 +23,7 @@ typedef enum eTask { MAIN_WORK, ADC_WORK, ONEWIRE_WORK, + SPI_TC_WORK, UI_WORK, REFLOW_WORK, NV_WORK, From b2917c8f8f727262500e9a89d8a221f2eb2634a6 Mon Sep 17 00:00:00 2001 From: Werner Johansson Date: Sat, 20 Dec 2014 22:04:48 -0800 Subject: [PATCH 2/4] Correct SPI_TC_Work timing Should run 10 times per second if SPI was initially detected --- src/max31855.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/max31855.c b/src/max31855.c index d48ead1..58a38ff 100644 --- a/src/max31855.c +++ b/src/max31855.c @@ -30,7 +30,7 @@ int16_t spiextrareadout[MAX_SPI_DEVICES]; // Keeps last readout from each device int numspidevices = 0; static int32_t SPI_TC_Work( void ) { - int32_t retval = TICKS_MS(100); + int32_t retval; for( int i = 0; i < numspidevices; i++ ) { SPIxfer_t xfer; @@ -44,7 +44,7 @@ static int32_t SPI_TC_Work( void ) { spiextrareadout[i] = tmp; } } - return retval; + return TICKS_MS(100); } uint32_t SPI_TC_Init( void ) { From 36d21ed355a835b851b16b7374731d4bbe97ce51 Mon Sep 17 00:00:00 2001 From: Werner Johansson Date: Sat, 20 Dec 2014 22:07:11 -0800 Subject: [PATCH 3/4] Add debug output if SPIxfer has an invalid length Might facilitate debugging. Also make mental note to add a timeout to the do/while loop so we don't get stuck (forcing the wdog to kick in) --- src/sc18is602b.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sc18is602b.c b/src/sc18is602b.c index 4a3ec64..c8b126e 100644 --- a/src/sc18is602b.c +++ b/src/sc18is602b.c @@ -43,9 +43,13 @@ int32_t SC18IS602B_Init( SPIclk_t clk, SPImode_t mode, SPIorder_t order ) { int32_t SC18IS602B_SPI_Xfer( SPIxfer_t* item ) { int32_t retval; - if( item->len > (sizeof(SPIxfer_t) - 2) ) return -1; // Invalid length + if( item->len > (sizeof(SPIxfer_t) - 2) ) { + printf("\n%s: Invalid length!",__FUNCTION__); + return -1; + } retval = I2C_Xfer(SCADDR, (uint8_t*)item, item->len + 1, 1); // Initialize transfer, ssmask + data if( retval == 0 ) { + // TODO: There should be a timeout here do { retval = I2C_Xfer(SCADDR + 1, (uint8_t*)item->data, item->len, 1); // Initialize read transfer, data only } while( retval != 0 ); // Wait for chip to be done with transaction From a1822c595fdf041a5bcbf4bdfb79b194b01a0989 Mon Sep 17 00:00:00 2001 From: Werner Johansson Date: Sun, 21 Dec 2014 09:18:37 -0800 Subject: [PATCH 4/4] Bugfix SPI_TC_Init numspidevices handling An incorrect assumption was made that SPI_TC_Work could be used during init (before numspidevices was properly initialized). numspidevices variable is now properly initialized before attemting to probe (and still kept at zero until init is run). Thanks to patrickwtlaw for tracking this thing down! --- src/max31855.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/max31855.c b/src/max31855.c index 58a38ff..3f6cefe 100644 --- a/src/max31855.c +++ b/src/max31855.c @@ -48,7 +48,6 @@ static int32_t SPI_TC_Work( void ) { } uint32_t SPI_TC_Init( void ) { - uint32_t numspidevices = 0; printf("\n%s called",__FUNCTION__); Sched_SetWorkfunc( SPI_TC_WORK, SPI_TC_Work ); @@ -60,7 +59,9 @@ uint32_t SPI_TC_Init( void ) { if( SC18IS602B_Init( SPICLK_1843KHZ, SPIMODE_0, SPIORDER_MSBFIRST ) >= 0 ) { // Only continue of we find the I2C to SPI bridge chip printf("\nProbing for MAX31855 devices..."); + numspidevices = MAX_SPI_DEVICES; // Assume all devices are present for SPI_TC_Work SPI_TC_Work(); // Run one iteration to update all data + numspidevices = 0; // And reset it afterwards for( int i = 0; i < MAX_SPI_DEVICES; i++ ) { if( (spidevreadout[i] == -1 && spiextrareadout[i] == -1) ||