diff --git a/tibbits/tbt61/tbt61.tbh b/tibbits/tbt61/tbt61.tbh
new file mode 100644
index 0000000..60d4534
--- /dev/null
+++ b/tibbits/tbt61/tbt61.tbh
@@ -0,0 +1,83 @@
+
+' VOLTAGE AND CURRENT INPUT SELECTION MAPPING
+#define VIN1_DIFFERENTIAL 0
+#define VIN2_DIFFERENTIAL 2
+#define VIN1+_SINGLE_ENDED 0
+#define VIN1-_SINGLE_ENDED 1
+#define VIN2+_SINGLE_ENDED 2
+#define VIN2-_SINGLE_ENDED 3
+#define IIN1_SINGLE_ENDED 4
+#define IIN2_SINGLE_ENDED 5
+
+enum TBT61_INIT_RESULT
+ TBT61_INIT_OK,
+ TBT61_INIT_ERROR_SPI_NO_EMPTY_CHANNEL,
+ TBT61_INT_ERROR_NO_TIBBIT_PRESENT,
+ TBT61_INIT_ERROR_NO_VALID_VERSION,
+ TBT61_INIT_ERROR_FAULT_CHECK_POWER
+end enum
+
+enum TBT61_VOLAGE_TYPE_INPUT
+ TBT61_VOLTAGE_TWO_DIFFERENTIAL,
+ TBT61_VOLTAGE_FOUR_SINGLE
+end enum
+
+type FW_Info
+ TibbitType as string(4)
+ SerialNumber(4) as byte
+ TestVersion(2) as byte
+ TestDate(3) as byte
+end type
+
+declare function tbt61_init(signature as string, input_type as TBT61_VOLAGE_TYPE_INPUT, cs as pl_io_num, clk as pl_io_num, mosi as pl_io_num, miso as pl_io_num, scl as pl_io_num, sda as pl_io_num, byref tbt_channel as byte) as TBT61_INIT_RESULT
+'FUNCTION
+'The function initializes Tibbit #61.
+'Inputs:
+' signature - Text identifier of the resource owner.
+' input_type - The type of inputs used. The value is a member of the enum type TBT61_VOLTAGE_TYPE_INPUT.
+' 0-TBT61_VOLTAGE_TWO_DIFFERENTIAL - two differential volt inputs.
+' 1-TBT61_VOLTAGE_FOUR_SINGLE - four volt inputs.
+' cs, clk, mosi, miso,scl, sda - are the pin numbers for the corresponding Tibbit control signals according to the Tibbit installation location on the TPS board.
+'
+'Outputs:
+' The function returns a value of the enum type TBT61_INIT_RESULT.
+' 0-TBT61_INIT_OK - Initialization completed successfully.
+' 1-TBT61_INIT_ERROR_SPI_NO_EMPTY_CHANNEL - There are no SPI channels available for use..
+' 2-TBT61_INT_ERROR_NO_TIBBIT_PRESENT - No Tibbits#61 were found using the pin numbers provided.
+' 3-TBT61_INIT_ERROR_NO_VALID_VERSION - Incorrect version of Tibbit's equipment.
+' 4-TBT61_INIT_ERROR_FAULT_CHECK_POWER - Tibbit#61 internal power supply testing error.
+' tbt_channel - If the function returned result 0-TBT61_INIT_OK then this parameter contains the identifier of the current Tibbit.
+'All calls to this Tibbit must be made with the passing of this identifier.
+
+declare sub tbt61_release(tbt_channel as byte)
+'SUBROUTINE
+'The subroutine releases all allocated resources for this Tibbit#61 instance.
+'Inputs:
+' tbt_channel - Tibbit#61 instance identifier.
+
+declare sub tbt61_mode(tbt_channel as byte, input_type as TBT61_VOLAGE_TYPE_INPUT)
+'SUBROUTINE
+'This subroutine changes the type of inputs used.
+'Inputs:
+' tbt_channel - Tibbit#61 instance identifier.
+' input_type - The type of inputs used. The value is a member of the enum type TBT61_VOLTAGE_TYPE_INPUT.
+' 0-TBT61_VOLTAGE_TWO_DIFFERENTIAL - two differential volt inputs.
+' 1-TBT61_VOLTAGE_FOUR_SINGLE - four volt inputs.
+
+declare function tbt61_read_adc(tbt_channel as byte, channel as byte, byref flags as byte) as real
+'FUNCTION
+'The function reads the ADC value for the specified channel number. Error flags are also returned.
+'Inputs:
+' tbt_channel - Tibbit#61 instance identifier.
+' channel - ADC channel number.
+'Outputs:
+' This function returns the measurement result for the specified channel. The result is in REAL format.
+' flags - Measurement result flags.
+
+declare function tbt61_read_fw_info(tbt_channel as byte) as FW_Info
+'FUNCTION
+'This function returns the FW_Info structure read from the EEPROM of the specified Tibbit#61.
+'Inputs:
+' tbt_channel - Tibbit#61 instance identifier.
+'Outputs:
+' info - Read FW_Info structure from Tibbit#61.
diff --git a/tibbits/tbt61/tbt61.tbs b/tibbits/tbt61/tbt61.tbs
new file mode 100644
index 0000000..0d67c5d
--- /dev/null
+++ b/tibbits/tbt61/tbt61.tbs
@@ -0,0 +1,1008 @@
+include "global.tbh"
+
+const TBT61_INIT_SIGNATURE = &h4453
+const TBT61_CR_LF = chr(13) + chr(10)
+const TBT61_DEBUG_STAMP = "TBT61> "
+const TBT61_MAX_NUM = 4
+
+#if TBT61_DEBUG_PRINT
+declare sub tbt61_debug_print(print_data as string)
+#endif
+
+#define EEPROM_ADDR_W &ha0
+#define EEPROM_ADDR_R &ha1
+#define EEPROM_SER_W &hb0
+#define EEPROM_SER_R &hb1
+
+#define CMD_WEN &b00000000
+#define CMD_READ &b01000000
+#define CMD_WRITE &b00000000
+#define ADDRESS_STATUS &h00
+#define ADDRESS_ADCMODE &h01
+#define ADDRESS_IFMODE &h02
+#define ADDRESS_REGCHECK &h03
+#define ADDRESS_DATA &h04
+#define ADDRESS_GPIOCON &h06
+#define ADDRESS_ID &h07
+#define ADDRESS_CH0 &h10
+#define ADDRESS_CH1 &h11
+#define ADDRESS_CH2 &h12
+#define ADDRESS_CH3 &h13
+#define ADDRESS_CH4 &h14
+#define ADDRESS_CH5 &h15
+#define ADDRESS_CH6 &h16
+#define ADDRESS_CH7 &h17
+#define ADDRESS_CH8 &h18
+#define ADDRESS_CH9 &h19
+#define ADDRESS_CH10 &h1a
+#define ADDRESS_CH11 &h1b
+#define ADDRESS_CH12 &h1c
+#define ADDRESS_CH13 &h1d
+#define ADDRESS_CH14 &h1e
+#define ADDRESS_CH15 &h1f
+#define ADDRESS_SETUPCON0 &h20
+#define ADDRESS_SETUPCON1 &h21
+#define ADDRESS_SETUPCON2 &h22
+#define ADDRESS_SETUPCON3 &h23
+#define ADDRESS_SETUPCON4 &h24
+#define ADDRESS_SETUPCON5 &h25
+#define ADDRESS_SETUPCON6 &h26
+#define ADDRESS_SETUPCON7 &h27
+#define ADDRESS_FILTCON0 &h28
+#define ADDRESS_FILTCON1 &h29
+#define ADDRESS_FILTCON2 &h2a
+#define ADDRESS_FILTCON3 &h2b
+#define ADDRESS_FILTCON4 &h2c
+#define ADDRESS_FILTCON5 &h2d
+#define ADDRESS_FILTCON6 &h2e
+#define ADDRESS_FILTCON7 &h2f
+#define ADDRESS_OFFSET0 &h30
+#define ADDRESS_OFFSET1 &h31
+#define ADDRESS_OFFSET2 &h32
+#define ADDRESS_OFFSET3 &h33
+#define ADDRESS_OFFSET4 &h34
+#define ADDRESS_OFFSET5 &h35
+#define ADDRESS_OFFSET6 &h36
+#define ADDRESS_OFFSET7 &h37
+#define ADDRESS_GAIN0 &h38
+#define ADDRESS_GAIN1 &h39
+#define ADDRESS_GAIN2 &h3a
+#define ADDRESS_GAIN3 &h3b
+#define ADDRESS_GAIN4 &h3c
+#define ADDRESS_GAIN5 &h3d
+#define ADDRESS_GAIN6 &h3e
+#define ADDRESS_GAIN7 &h3f
+
+' ADC MODE
+#define ADC_MODE_REF_EN &h8000
+#define ADC_MODE_SING_CYC &h2000
+#define ADC_MODE_DELAY_0US &h0000
+#define ADC_MODE_DELAY_32US &h0100
+#define ADC_MODE_DELAY_128US &h0200
+#define ADC_MODE_DELAY_320US &h0300
+#define ADC_MODE_DELAY_800US &h0400
+#define ADC_MODE_DELAY_1600US &h0500
+#define ADC_MODE_DELAY_4MS &h0600
+#define ADC_MODE_DELAY_8MS &h0700
+#define ADC_MODE_CONTINUOUS &h0000
+#define ADC_MODE_SINGLE &h0010
+#define ADC_MODE_STANDBY &h0020
+#define ADC_MODE_POWERDOWN &h0030
+#define ADC_MODE_INTERNAL_OFFSET_CALIBRATION &h0040
+#define ADC_MODE_INTERNAL_GAIN_CALIBRATION &h0050
+#define ADC_MODE_SYSTEM_OFFSET_CALIBRATION &h0060
+#define ADC_MODE_SYSTEM_GAIN_CALIBRATION &h0070
+#define ADC_MODE_INTERNAL_OSC &h0000
+#define ADC_MODE_INTERNAL_OSC_XTAL2OUT &h0004
+#define ADC_MODE_EXTERNAL_XTAL2IN &h0008
+#define ADC_MODE_EXTERNAL_OSC &h000c
+
+' INTERFACE MODE
+#define IF_MODE_ALT_SYNC &h1000
+#define IF_MODE_IOSTRENGTH &h0800
+#define IF_MODE_DOUT_RESET &h0100
+#define IF_MODE_CONTREAD &h0080
+#define IF_MODE_DATA_STAT &h0040
+#define IF_MODE_REG_CHECK &h0020
+#define IF_MODE_CRC_DISABLE &h0000
+#define IF_MODE_CRC_XOR &h0004
+#define IF_MODE_CRC_CRC8 &h0008
+#define IF_MODE_WL16 &h0001
+
+' CHANNEL CONTROL
+#define CHANNEL_ENABLE &h8000
+#define CHANNEL_SETUP0 &h0000
+#define CHANNEL_SETUP1 &h1000
+#define CHANNEL_SETUP2 &h2000
+#define CHANNEL_SETUP3 &h3000
+#define CHANNEL_SETUP4 &h4000
+#define CHANNEL_SETUP5 &h5000
+#define CHANNEL_SETUP6 &h6000
+#define CHANNEL_SETUP7 &h7000
+#define CHANNEL_INPUT_VIN0_VIN1 &h0001
+#define CHANNEL_INPUT_VIN0_VINCOM &h0010
+#define CHANNEL_INPUT_VIN1_VIN0 &h0020
+#define CHANNEL_INPUT_VIN1_VINCOM &h0030
+#define CHANNEL_INPUT_VIN2_VIN3 &h0043
+#define CHANNEL_INPUT_VIN2_VINCOM &h0050
+#define CHANNEL_INPUT_VIN3_VIN2 &h0062
+#define CHANNEL_INPUT_VIN3_VINCOM &h0070
+#define CHANNEL_INPUT_VIN4_VIN5 &h0085
+#define CHANNEL_INPUT_VIN4_VINCOM &h0090
+#define CHANNEL_INPUT_VIN5_VIN4 &h00a4
+#define CHANNEL_INPUT_VIN5_VINCOM &h00b0
+#define CHANNEL_INPUT_VIN6_VIN7 &h00c7
+#define CHANNEL_INPUT_VIN6_VINCOM &h00d0
+#define CHANNEL_INPUT_VIN7_VIN6 &h00e6
+#define CHANNEL_INPUT_VIN7_VINCOM &h00f0
+#define CHANNEL_INPUT_IIN3P_IIN3N &h018b
+#define CHANNEL_INPUT_IIN2P_IIN2N &h01aa
+#define CHANNEL_INPUT_IIN1P_IIN1N &h01c9
+#define CHANNEL_INPUT_IIN0P_IIN0N &h01e8
+#define CHANNEL_INPUT_TEMPSENSOR &h0232
+#define CHANNEL_INPUT_REFERENCE &h02b6
+
+' SETUP CONTROL
+#define SETUP_UNIPOLAR &h0000
+#define SETUP_BIPOLAR &h1000
+#define SETUP_REFBUFP_DISABLE &h0000
+#define SETUP_REFBUFP_ENABLE &h0800
+#define SETUP_REFBUFN_DISABLE &h0000
+#define SETUP_REFBUFN_ENABLE &h0400
+#define SETUP_INPBUF_DISABLE &h0000
+#define SETUP_INPBUF_ENABLE &h0300
+#define SETUP_REF_SEL_EXTERNAL_REF &h0000
+#define SETUP_REF_SEL_INTERNAL_2V5 &h0020
+#define SETUP_REF_SEL_AVDD &h0030
+
+' FILTER CONTROL
+#define SINC3_MAP &h8000
+#define ENHFILTEN &h0800
+#define ENHFILT_27SPS &h0200
+#define ENHFILT_25SPS &h0300
+#define ENHFILT_20SPS &h0500
+#define ENHFILT_17SPS &h0600
+#define ORDER_SINC5 &h0000
+#define ORDER_SINC3 &h0060
+#define ODR_31250SPS &h0000
+#define ODR_15625SPS &h0005
+#define ODR_10417SPS &h0007
+#define ODR_5208SPS &h0008
+#define ODR_2597SPS &h0009
+#define ODR_1007SPS &h000a
+#define ODR_503SPS &h000b
+#define ODR_381SPS &H000c
+#define ODR_200SPS &h000d
+#define ODR_100SPS &h000e
+#define ODR_59SPS &h000f
+#define ODR_49SPS &h0010
+#define ODR_20SPS &h0011
+#define ODR_16SPS &h0012
+#define ODR_10SPS &h0013
+#define ODR_5SPS &h0014
+#define ODR_2_5SPS &h0015
+#define ODR_1_25SPS &h0016
+
+declare function tbt61_get_status(tbt_channel as byte) as byte
+declare sub tbt61_send_command(tbt_channel as byte, command as byte)
+declare sub tbt61_set_adc_mode(tbt_channel as byte, mode as word)
+declare sub tbt61_set_interface_mode(tbt_channel as byte, mode as word)
+declare sub tbt61_set_channel(tbt_channel as byte, channel as byte, channel_control as word)
+declare sub tbt61_set_filter(tbt_channel as byte, channel as byte, filter_control as word)
+declare sub tbt16_set_setup(tbt_channel as byte, num as byte, control as word)
+declare sub tbt61_reset(tbt_channel as byte)
+declare function tbt61_get_reg8(tbt_channel as byte, num as byte) as byte
+declare function tbt61_get_reg16(tbt_channel as byte, num as byte) as word
+declare function tbt61_get_reg24(tbt_channel as byte, num as byte) as dword
+declare sub tbt61_set_calibration_offset(tbt_channel as byte, value as dword, channel as byte)
+declare sub tbt61_set_calibration_gain(tbt_channel as byte, value as dword, channel as byte)
+
+dim tbt61_init_flag as word
+dim tbt61_num_used as byte
+
+type tbt61
+ use as boolean
+ ssi_num as byte
+ i2c_num as byte
+ input_type as TBT61_VOLAGE_TYPE_INPUT
+ cs as pl_io_num
+ clk as pl_io_num
+ mosi as pl_io_num
+ miso as pl_io_num
+ scl as byte
+ sda as byte
+
+ calibr_offset(6) as dword
+ calibr_gain(6) as dword
+ offset_coeff(6) as long
+ gain_coeff(6) as real
+ calibr_applied as boolean
+
+end type
+
+dim calibr_check_sum as dword
+
+dim tibbitsPlace(TBT61_MAX_NUM) as tbt61
+
+sub tbt61_set_hw(tbt_channel as byte)
+
+ io.num = tibbitsPlace(tbt_channel).cs
+ io.enabled=YES
+
+ io.num = tibbitsPlace(tbt_channel).clk
+ io.enabled=YES
+
+ io.num = tibbitsPlace(tbt_channel).mosi
+ io.enabled=YES
+
+ io.num = tibbitsPlace(tbt_channel).miso
+ io.enabled=NO
+
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.enabled = NO
+ ssi.zmode = PL_SSI_ZMODE_ALWAYS_ENABLED
+ ssi.mode = PL_SSI_MODE_3
+ ssi.direction = PL_SSI_DIRECTION_LEFT
+ ssi.clkmap = tibbitsPlace(tbt_channel).clk
+ ssi.dimap = tibbitsPlace(tbt_channel).miso
+ ssi.domap = tibbitsPlace(tbt_channel).mosi
+ ssi.baudrate = 14
+ ssi.enabled = YES
+
+ io.num = tibbitsPlace(tbt_channel).cs
+ io.enabled = YES
+ io.state = HIGH
+
+end sub
+
+function tbt61_get_calibr(tbt_channel as byte) as boolean
+
+ dim i as byte
+ dim cs as dword
+ dim op as dword
+
+ tbt61_get_calibr = false
+
+ si2c_get(tibbitsPlace(tbt_channel).i2c_num)
+
+ cs = 0
+ for i = 0 to 5
+ si2c_start()
+ si2c_write(EEPROM_ADDR_W)
+ si2c_write(i * 8)
+ si2c_start()
+ si2c_write(EEPROM_ADDR_R)
+
+ op = si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ tibbitsPlace(tbt_channel).calibr_offset(i) = op
+ op = si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ op = (op * 256) + si2c_read(false)
+ tibbitsPlace(tbt_channel).calibr_gain(i) = op
+ cs = cs + tibbitsPlace(tbt_channel).calibr_offset(i) + tibbitsPlace(tbt_channel).calibr_gain(i)
+
+ si2c_stop()
+ next i
+
+ si2c_start()
+ si2c_write(EEPROM_ADDR_W)
+ si2c_write(6 * 8)
+ si2c_start()
+ si2c_write(EEPROM_ADDR_R)
+
+ op = si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ op = (op * 256) + si2c_read(true)
+ op = (op * 256) + si2c_read(false)
+ calibr_check_sum = op
+
+ si2c_stop()
+
+ if calibr_check_sum = cs then
+ tbt61_get_calibr = true
+ tibbitsPlace(tbt_channel).calibr_applied = true
+ else
+ for i = 0 to 5
+ tibbitsPlace(tbt_channel).calibr_offset(i) = &h00800000
+ tibbitsPlace(tbt_channel).calibr_gain(i) = &h005810d0
+ next i
+ tibbitsPlace(tbt_channel).calibr_applied = false
+ end if
+
+end function
+
+function tbt61_check_library(tbt_channel as byte) as boolean
+
+ if tbt61_init_flag <> TBT61_INIT_SIGNATURE then
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("The lib is not initialized, call tbt61_init() first")
+ #endif
+ tbt61_check_library = false
+ exit function
+ end if
+
+ if tbt_channel >= TBT61_MAX_NUM then
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("Channel not use")
+ #endif
+ tbt61_check_library = false
+ exit function
+ end if
+
+ if tibbitsPlace(tbt_channel).use = NO then
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("Channel not use")
+ #endif
+ tbt61_check_library = false
+ exit function
+ end if
+
+ tbt61_check_library = true
+
+end function
+
+sub tbt61_set_channels(tbt_channel as byte)
+
+ tbt61_set_filter(tbt_channel, 0, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 1, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 2, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 3, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 4, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 5, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 6, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ tbt61_set_filter(tbt_channel, 7, ENHFILTEN or ENHFILT_17SPS or ORDER_SINC5 or ODR_1_25SPS)
+ if tibbitsPlace(tbt_channel).input_type = TBT61_VOLTAGE_TWO_DIFFERENTIAL then
+ tbt61_set_channel(tbt_channel, 0, CHANNEL_ENABLE or CHANNEL_SETUP4 or CHANNEL_INPUT_VIN0_VIN1)
+ tbt61_set_channel(tbt_channel, 1, CHANNEL_ENABLE or CHANNEL_SETUP4 or CHANNEL_INPUT_VIN0_VIN1)
+ tbt61_set_channel(tbt_channel, 2, CHANNEL_ENABLE or CHANNEL_SETUP5 or CHANNEL_INPUT_VIN2_VIN3)
+ tbt61_set_channel(tbt_channel, 3, CHANNEL_ENABLE or CHANNEL_SETUP5 or CHANNEL_INPUT_VIN2_VIN3)
+ else
+ tbt61_set_channel(tbt_channel, 0, CHANNEL_ENABLE or CHANNEL_SETUP0 or CHANNEL_INPUT_VIN0_VINCOM)
+ tbt61_set_channel(tbt_channel, 1, CHANNEL_ENABLE or CHANNEL_SETUP1 or CHANNEL_INPUT_VIN1_VINCOM)
+ tbt61_set_channel(tbt_channel, 2, CHANNEL_ENABLE or CHANNEL_SETUP2 or CHANNEL_INPUT_VIN2_VINCOM)
+ tbt61_set_channel(tbt_channel, 3, CHANNEL_ENABLE or CHANNEL_SETUP3 or CHANNEL_INPUT_VIN3_VINCOM)
+ end if
+ tbt61_set_channel(tbt_channel, 4, CHANNEL_ENABLE or CHANNEL_SETUP7 or CHANNEL_INPUT_IIN0P_IIN0N)
+ tbt61_set_channel(tbt_channel, 5, CHANNEL_ENABLE or CHANNEL_SETUP7 or CHANNEL_INPUT_IIN1P_IIN1N)
+
+ tbt61_set_channel(tbt_channel, 6, CHANNEL_ENABLE or CHANNEL_SETUP6 or CHANNEL_INPUT_VIN6_VINCOM)
+ tbt61_set_channel(tbt_channel, 7, CHANNEL_ENABLE or CHANNEL_SETUP6 or CHANNEL_INPUT_VIN7_VINCOM)
+
+end sub
+
+sub tbt61_calibr_append(tbt_channel as byte)
+
+ dim i as byte
+ dim res as float
+ dim off as long
+
+ ' Load calibration values into ADC
+ for i = 0 to 5
+ tbt61_set_calibration_offset(tbt_channel, tibbitsPlace(tbt_channel).calibr_offset(i), i)
+ tbt61_set_calibration_gain(tbt_channel, tibbitsPlace(tbt_channel).calibr_gain(i), i)
+
+ ' Calc calibration coefficient
+ off = tibbitsPlace(tbt_channel).calibr_offset(i)
+ tibbitsPlace(tbt_channel).offset_coeff(i) = (off - 8388608) * 2.5
+ if i < 4 then
+ res = 5242880
+ res = res / tibbitsPlace(tbt_channel).calibr_gain(i)
+ tibbitsPlace(tbt_channel).gain_coeff(i) = res
+ else
+ res = 10485760
+ res = res / tibbitsPlace(tbt_channel).calibr_gain(i)
+ tibbitsPlace(tbt_channel).gain_coeff(i) = res
+ end if
+ next i
+
+end sub
+
+sub tbt61_set_mode(tbt_channel as byte)
+
+ tbt61_set_adc_mode(tbt_channel, ADC_MODE_REF_EN or ADC_MODE_DELAY_320US or ADC_MODE_CONTINUOUS or ADC_MODE_INTERNAL_OSC)
+ tbt61_set_interface_mode(tbt_channel, IF_MODE_DATA_STAT or IF_MODE_DOUT_RESET or IF_MODE_CRC_DISABLE)
+
+ 'Set SETUP configuration
+ ' Set SETUP for Voltage inputs
+ tbt16_set_setup(tbt_channel, 0, SETUP_UNIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+ tbt16_set_setup(tbt_channel, 1, SETUP_UNIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+ tbt16_set_setup(tbt_channel, 2, SETUP_UNIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+ tbt16_set_setup(tbt_channel, 3, SETUP_UNIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+ tbt16_set_setup(tbt_channel, 4, SETUP_BIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+ tbt16_set_setup(tbt_channel, 5, SETUP_BIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+ tbt16_set_setup(tbt_channel, 6, SETUP_UNIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_ENABLE or SETUP_REF_SEL_INTERNAL_2V5)
+
+ ' Set SETUP for Current inputs
+ tbt16_set_setup(tbt_channel, 7, SETUP_BIPOLAR or SETUP_REFBUFP_DISABLE or SETUP_REFBUFN_DISABLE or SETUP_INPBUF_DISABLE or SETUP_REF_SEL_INTERNAL_2V5)
+
+ ' Setup channels
+ tbt61_set_channels(tbt_channel)
+
+end sub
+
+sub tbt61_mode(tbt_channel as byte, input_type as TBT61_VOLAGE_TYPE_INPUT)
+
+ tibbitsPlace(tbt_channel).input_type = input_type
+
+ ' Set normal mode
+ tbt61_set_mode(tbt_channel)
+
+end sub
+
+function tbt61_init(signature as string, input_type as TBT61_VOLAGE_TYPE_INPUT, cs as pl_io_num, clk as pl_io_num, mosi as pl_io_num, miso as pl_io_num, scl as pl_io_num, sda as pl_io_num, byref tbt_channel as byte) as TBT61_INIT_RESULT
+
+ dim i as byte
+ dim volt as real
+ dim flags as byte
+ dim calibr_ready as boolean
+
+ if (tbt61_init_flag <> TBT61_INIT_SIGNATURE) then
+ for i = 0 to TBT61_MAX_NUM - 1
+ tibbitsPlace(i).use = false
+ tibbitsPlace(i).ssi_num = 255
+ tibbitsPlace(i).i2c_num = 255
+ tibbitsPlace(i).input_type = TBT61_VOLTAGE_TWO_DIFFERENTIAL
+ tibbitsPlace(i).cs = 0
+ tibbitsPlace(i).clk = 0
+ tibbitsPlace(i).mosi = 0
+ tibbitsPlace(i).miso = 0
+ next i
+ tbt61_init_flag = TBT61_INIT_SIGNATURE
+ tbt61_num_used = 0
+ end if
+
+ if tbt61_num_used >= TBT61_MAX_NUM then
+ tbt61_init = TBT61_INIT_ERROR_SPI_NO_EMPTY_CHANNEL
+ exit function
+ end if
+
+ tbt61_init = TBT61_INIT_OK
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("Init start...")
+ #endif
+
+ i = 0
+ do until tibbitsPlace(i).use = false
+ i = i + 1
+ loop
+
+ tibbitsPlace(i).use = true
+ tibbitsPlace(i).input_type = input_type
+ tibbitsPlace(i).cs = cs
+ tibbitsPlace(i).clk = clk
+ tibbitsPlace(i).mosi = mosi
+ tibbitsPlace(i).miso = miso
+ tibbitsPlace(i).scl = scl
+ tibbitsPlace(i).sda = sda
+
+ tbt_channel = i
+ tbt61_num_used = tbt61_num_used + 1
+
+ ' HW init
+ tibbitsPlace(tbt_channel).ssi_num = ssi_get(signature)
+ if tibbitsPlace(tbt_channel).ssi_num = 255 then
+ tibbitsPlace(tbt_channel).ssi_num = 255
+ tibbitsPlace(tbt_channel).use = false
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("SSI channel not available!")
+ tbt61_init = TBT61_INIT_ERROR_SPI_NO_EMPTY_CHANNEL
+ exit function
+ #endif
+ else
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("SSI channel: " + str(tibbitsPlace(tbt_channel).ssi_num))
+ #endif
+ end if
+
+ tibbitsPlace(tbt_channel).i2c_num = si2c_register(signature, sda, scl, NO)
+
+ if tbt61_get_calibr(tbt_channel) then
+ calibr_ready = true
+ else
+ calibr_ready = false
+ end if
+
+ tbt61_set_hw(tbt_channel)
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("HW reset...")
+ #endif
+
+ ' Chip reset
+ tbt61_reset(tbt_channel)
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("HW check ID...")
+ #endif
+
+ ' SW test
+ ' ID read
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_READ or ADDRESS_ID)
+
+ ' Read data
+ dim id as word
+ id = ssi.value(0, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ if id and &hfff0 <> &h30d0 then
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("Unknown device!")
+ #endif
+ ssi_release(tibbitsPlace(tbt_channel).ssi_num)
+ tibbitsPlace(tbt_channel).ssi_num = 255
+ tibbitsPlace(tbt_channel).use = false
+ tbt61_num_used = tbt61_num_used - 1
+
+ if id = &hffff then
+ tbt61_init = TBT61_INT_ERROR_NO_TIBBIT_PRESENT
+ else
+ tbt61_init = TBT61_INIT_ERROR_NO_VALID_VERSION
+ end if
+ exit function
+ end if
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("FW info read...")
+ #endif
+
+ ' Read FW Info
+ dim info as FW_Info
+ info = tbt61_read_fw_info(tbt_channel)
+
+ #if TBT61_DEBUG_PRINT = 1
+ if info.TibbitType <> chr(255) + chr(255) + chr(255) + chr(255) then
+ tbt61_debug_print("HW type: " + info.TibbitType)
+ tbt61_debug_print("HW serial: " + str(info.SerialNumber(0)) + str(info.SerialNumber(1)) + str(info.SerialNumber(2)) + str(info.SerialNumber(3)))
+ tbt61_debug_print("HW version: " + str(info.TestVersion(0)) + "." + str(info.TestVersion(1)))
+ tbt61_debug_print("HW date: " + str(info.TestDate(0)) + "." + str(info.TestDate(1)) + "." + str(info.TestDate(2)))
+ else
+ tbt61_debug_print("FW info not present!")
+ end if
+ #endif
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("HW setup...")
+ #endif
+
+ 'Set SETUP configuration
+ tbt61_set_mode(tbt_channel)
+
+ if calibr_ready = true then
+ tbt61_calibr_append(tbt_channel)
+ end if
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("HW internal voltage check...")
+ #endif
+
+ ' Check internal voltages
+ if info.TibbitType = "61-1" then
+ volt = tbt61_read_adc(tbt_channel, 6, flags)
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("High voltage: " + ftostr(volt * 10, FTOSTR_MODE_PLAIN, 3))
+ #endif
+ if volt < 2.0 or volt > 2.8 or flags <> &h00 then
+ ' 2.4 voltage fault
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("24V check fault!")
+ #endif
+ ssi_release(tibbitsPlace(tbt_channel).ssi_num)
+ tibbitsPlace(tbt_channel).ssi_num = 255
+ tibbitsPlace(tbt_channel).use = false
+ tbt61_num_used = tbt61_num_used - 1
+ tbt61_init = TBT61_INIT_ERROR_FAULT_CHECK_POWER
+ exit function
+ else
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("24V check passed")
+ #endif
+ end if
+ end if
+
+ volt = tbt61_read_adc(tbt_channel, 7, flags)
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("VDD voltage: " + ftostr(volt, FTOSTR_MODE_PLAIN, 3))
+ #endif
+ if volt < 4.5 or volt > 5.65 or flags <> &h00 then
+ ' 5.0 voltage fault
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("5.0V check fault!")
+ #endif
+ ssi_release(tibbitsPlace(tbt_channel).ssi_num)
+ tibbitsPlace(tbt_channel).ssi_num = 255
+ tibbitsPlace(tbt_channel).use = false
+ tbt61_num_used = tbt61_num_used - 1
+ tbt61_init = TBT61_INIT_ERROR_FAULT_CHECK_POWER
+ exit function
+ else
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("5.0V check passed")
+ #endif
+ end if
+
+ #if TBT61_DEBUG_PRINT = 1
+ tbt61_debug_print("Init complete!")
+ #endif
+
+ tbt61_init = TBT61_INIT_OK
+
+end function
+
+sub tbt61_release(tbt_channel as byte)
+
+ if tbt_channel < TBT61_MAX_NUM then
+
+ if tibbitsPlace(tbt_channel).ssi_num <> 255 then
+ ssi_release(tibbitsPlace(tbt_channel).ssi_num)
+ end if
+ tibbitsPlace(tbt_channel).use = false
+ tibbitsPlace(tbt_channel).ssi_num = 255
+ tibbitsPlace(tbt_channel).input_type = TBT61_VOLTAGE_TWO_DIFFERENTIAL
+ tibbitsPlace(tbt_channel).cs = 0
+ tibbitsPlace(tbt_channel).clk = 0
+ tibbitsPlace(tbt_channel).mosi = 0
+ tibbitsPlace(tbt_channel).miso = 0
+
+ tbt61_num_used = tbt61_num_used - 1
+ end if
+
+end sub
+
+sub tbt16_set_setup(tbt_channel as byte, num as byte, control as word)
+
+ if num < 8 then
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_SETUPCON0 + num)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(control, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ end if
+
+end sub
+
+sub tbt61_set_channel(tbt_channel as byte, channel as byte, channel_control as word)
+
+ if channel < 16 then
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_CH0 + channel)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(channel_control, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ end if
+
+end sub
+
+sub tbt61_set_filter(tbt_channel as byte, channel as byte, filter_control as word)
+
+ if channel < 16 then
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_FILTCON0 + channel)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(filter_control, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ end if
+
+end sub
+
+sub tbt61_set_adc_mode(tbt_channel as byte, mode as word)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_ADCMODE)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(mode, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+end sub
+
+
+sub tbt61_set_interface_mode(tbt_channel as byte, mode as word)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_IFMODE)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(mode, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+
+end sub
+
+sub tbt61_set_calibration_offset(tbt_channel as byte, value as dword, channel as byte)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_OFFSET0 + channel)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(value shr 8, 16)
+ ssi.value(value, 8)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+
+end sub
+
+sub tbt61_set_calibration_gain(tbt_channel as byte, value as dword, channel as byte)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_WRITE or ADDRESS_GAIN0 + channel)
+
+ ' Write mode
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(value shr 8, 16)
+ ssi.value(value, 8)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+
+end sub
+
+function tbt61_get_reg8(tbt_channel as byte, num as byte) as byte
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_READ or num)
+
+ ' Read data
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ tbt61_get_reg8 = ssi.value(&hff, 8)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+end function
+
+function tbt61_get_reg16(tbt_channel as byte, num as byte) as word
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_READ or num)
+
+ ' Read data
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ tbt61_get_reg16 = ssi.value(&hffff, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+end function
+
+function tbt61_get_reg24(tbt_channel as byte, num as byte) as dword
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_READ or num)
+
+ ' Read data
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ tbt61_get_reg24 = (ssi.value(&hffff, 16) shl 8) + ssi.value(&hff, 8)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+end function
+
+function tbt61_get_status(tbt_channel as byte) as byte
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_READ or ADDRESS_STATUS)
+
+ ' Read data
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ tbt61_get_status = ssi.value(&hff, 8)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+end function
+
+function tbt61_read_adc(tbt_channel as byte, channel as byte, byref flags as byte) as real
+
+ dim i as word
+ dim j as byte
+ dim lo, hi as word
+ dim res as real
+ dim coeff as byte
+
+ if tbt_channel >= TBT61_MAX_NUM or tbt_channel >= tbt61_num_used then
+ tbt61_read_adc = -100
+ flags = &h01
+ end if
+
+ if channel >= 8 then
+ tbt61_read_adc = -100
+ flags = &h02
+ end if
+
+ if tibbitsPlace(tbt_channel).calibr_applied = true then
+ if tibbitsPlace(tbt_channel).input_type = TBT61_VOLTAGE_TWO_DIFFERENTIAL then
+ if channel = 0 or channel = 1 then
+ coeff = 4
+ end if
+ if channel = 2 or channel = 3 then
+ coeff = 5
+ end if
+ else
+ coeff = channel
+ end if
+ end if
+
+ j = 0
+
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+
+ do
+ i = 0
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+ do ' wait /RDY
+ i = i + 1
+ if i > 10000 then
+ tbt61_read_adc = -100
+ flags = &h04
+ exit function
+ end if
+ loop while io.lineget(tibbitsPlace(tbt_channel).miso) = HIGH
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ' Send cmd
+ tbt61_send_command(tbt_channel, CMD_WEN or CMD_READ or ADDRESS_DATA)
+
+ ' Read data
+ hi = ssi.value(&hffff, 16)
+ lo = ssi.value(&hffff, 16)
+
+ j = j + 1
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ loop while ((lo and &h0007) <> channel) and j < 200
+
+ if j >= 200 then
+ tbt61_read_adc = -100 ' timeout
+ flags = &h04
+ else
+ res = ((hi shl 16) + lo) shr 8
+
+ if tibbitsPlace(tbt_channel).input_type = TBT61_VOLTAGE_TWO_DIFFERENTIAL then
+ ' DIFF MODE
+ if channel >= 0 and channel <= 3 then 'Vin bipolar
+ if tibbitsPlace(tbt_channel).calibr_applied = true then
+ tbt61_read_adc = ((res - 8388608) * tibbitsPlace(tbt_channel).gain_coeff(coeff) + tibbitsPlace(tbt_channel).offset_coeff(coeff)) / 629145.6
+ else
+ tbt61_read_adc = ((((res / 10) * 298) / 10) - 24998051) / 1000000
+ end if
+ end if
+ flags = lo and &h0040
+ else
+ ' SINGLE MODE
+ if channel >= 0 and channel <= 3 then 'Vin unipolar
+ if tibbitsPlace(tbt_channel).calibr_applied = true then
+ tbt61_read_adc = (res * tibbitsPlace(tbt_channel).gain_coeff(coeff) + tibbitsPlace(tbt_channel).offset_coeff(coeff)) / 629145.6
+ else
+ tbt61_read_adc = ((res * 149) / 100) / 1000000
+ end if
+ end if
+ flags = lo and &h0040
+ end if
+
+ if channel = 4 or channel = 5 then 'Iin bipolar
+ tbt61_read_adc = (((res - 8388608) * 5) / 83886) / 10
+ if tbt61_read_adc < 4 or tbt61_read_adc > 20 then
+ flags = (lo and &h0040) or &h20
+ else
+ flags = lo and &h0040
+ end if
+ end if
+
+ if channel = 6 or channel = 7 then 'Vin unipolar
+ tbt61_read_adc = ((res * 149) / 100) / 1000000
+ end if
+
+ end if
+
+end function
+
+sub tbt61_send_command(tbt_channel as byte, command as byte)
+
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(command, 8)
+
+end sub
+
+sub tbt61_reset(tbt_channel as byte)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, LOW)
+
+ ssi.channel = tibbitsPlace(tbt_channel).ssi_num
+ ssi.value(&hffff, 16)
+ ssi.value(&hffff, 16)
+ ssi.value(&hffff, 16)
+ ssi.value(&hffff, 16)
+
+ io.lineset(tibbitsPlace(tbt_channel).cs, HIGH)
+
+ sys.delayms(5)
+
+end sub
+
+function tbt61_read_fw_info(tbt_channel as byte) as FW_Info
+
+ si2c_get(tibbitsPlace(tbt_channel).i2c_num)
+
+ si2c_start()
+ si2c_write(EEPROM_ADDR_W)
+ si2c_write(&h60)
+ si2c_start()
+ si2c_write(EEPROM_ADDR_R)
+
+ tbt61_read_fw_info.TibbitType = ""
+ tbt61_read_fw_info.TibbitType = tbt61_read_fw_info.TibbitType + chr(si2c_read(true))
+ tbt61_read_fw_info.TibbitType = tbt61_read_fw_info.TibbitType + chr(si2c_read(true))
+ tbt61_read_fw_info.TibbitType = tbt61_read_fw_info.TibbitType + chr(si2c_read(true))
+ tbt61_read_fw_info.TibbitType = tbt61_read_fw_info.TibbitType + chr(si2c_read(true))
+ tbt61_read_fw_info.SerialNumber(0) = si2c_read(true)
+ tbt61_read_fw_info.SerialNumber(1) = si2c_read(true)
+ tbt61_read_fw_info.SerialNumber(2) = si2c_read(true)
+ tbt61_read_fw_info.SerialNumber(3) = si2c_read(true)
+ tbt61_read_fw_info.TestVersion(0) = si2c_read(true)
+ tbt61_read_fw_info.TestVersion(1) = si2c_read(true)
+ tbt61_read_fw_info.TestDate(0) = si2c_read(true)
+ tbt61_read_fw_info.TestDate(1) = si2c_read(true)
+ tbt61_read_fw_info.TestDate(2) = si2c_read(false)
+
+ si2c_stop()
+
+end function
+
+#if TBT61_DEBUG_PRINT
+sub tbt61_debug_print(print_data as string)
+ sys.debugprint(TBT61_DEBUG_STAMP + print_data + tbt61_CR_LF)
+end sub
+#endif
+