update for TAS2557 Dual Mono FTC
authorPeter Li <peter-li@ti.com>
Sat, 7 Jan 2017 01:28:30 +0000 (09:28 +0800)
committerPeter Li <peter-li@ti.com>
Sat, 7 Jan 2017 01:28:30 +0000 (09:28 +0800)
13 files changed:
Android.mk [new file with mode: 0755]
CleanSpec.mk [new file with mode: 0755]
factorytest.c [new file with mode: 0755]
lib/Android.mk [new file with mode: 0755]
lib/libftc32.a [new file with mode: 0755]
lib/libftc64.a [new file with mode: 0755]
speaker.ftcfg [new file with mode: 0755]
system.c [new file with mode: 0755]
system.h [new file with mode: 0755]
tas2557.c [new file with mode: 0755]
tas2557.h [new file with mode: 0755]
tas2557_ftc.h [new file with mode: 0755]
tas2557dm_ftc.c [new file with mode: 0755]

diff --git a/Android.mk b/Android.mk
new file mode 100755 (executable)
index 0000000..8790baf
--- /dev/null
@@ -0,0 +1,24 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES += \
+      factorytest.c \
+      system.c \
+      tas2557.c \
+      tas2557dm_ftc.c    
+
+LOCAL_C_INCLUDES += ${LOCAL_PATH}/
+
+LOCAL_CFLAGS += -Wno-unused-parameter
+
+LOCAL_SHARED_LIBRARIES += libm
+
+LOCAL_STATIC_LIBRARIES += libftc
+
+LOCAL_MODULE := factorytest
+
+include $(BUILD_EXECUTABLE)
+
+#include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/CleanSpec.mk b/CleanSpec.mk
new file mode 100755 (executable)
index 0000000..b84e1b6
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright (C) 2007 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# If you don't need to do a full clean build but would like to touch
+# a file or delete some intermediate files, add a clean step to the end
+# of the list.  These steps will only be run once, if they haven't been
+# run before.
+#
+# E.g.:
+#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
+#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
+#
+# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
+# files that are missing or have been moved.
+#
+# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
+# Use $(OUT_DIR) to refer to the "out" directory.
+#
+# If you need to re-do something that's already mentioned, just copy
+# the command and add it to the bottom of the list.  E.g., if a change
+# that you made last week required touching a file and a change you
+# made today requires touching the same file, just copy the old
+# touch step and add it to the end of the list.
+#
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
+
+# For example:
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
+#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
+#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
+#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
+
+# ************************************************
+# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
+# ************************************************
diff --git a/factorytest.c b/factorytest.c
new file mode 100755 (executable)
index 0000000..8933f57
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+** =============================================================================
+** Copyright (c) 2016  Texas Instruments Inc.
+**
+** 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; version 2.
+**
+** 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, write to the Free Software Foundation, Inc., 51 Franklin
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**
+** File:
+**     factorytest.c
+**
+** Description:
+**     main program for TAS2555 factory test 
+**
+** =============================================================================
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include "tas2557_ftc.h"
+
+// ================================================================ Definitions
+// Obtained from Speaker Manufacturer
+#define SPK_T_MAX            100    // Speaker Maximum Temperature (C)
+#define SPK_RE_TOL_PER       10     // Re +/- tolerance (%)
+#define SPK_RE_ALPHA         0.0039 // Temperature coefficient alpha (1/K)
+
+// Obtained from PurePath Console 3 (PPC3)
+#define PPC3_RE0             7.41   // Re0 (ohm)
+#define PPC3_RTV             46.5   // Rtv (K/W)
+#define PPC3_RTM             78.2   // Rtm (K/W)
+#define PPC3_RTVA            2460   // Rtva (K/W)
+#define PPC3_SYSGAIN         9.35   // System Gain (V/FS)
+#define PPC3_DEV_NONLIN_PER  1.5    // Device Non-linearity (%)
+#define PPC3_DELTA_T_LIMIT   80     // Delta Thermal Limit (C)
+#define FS_RATE              48000  // TAS2555 Sample Rate
+
+void ExitWithHint(char *pHint)
+{
+       printf("factorytest: invalid command line: %s\n\r\n\r", pHint);
+
+       printf("usage: factorytest [-t temperature] [-c configuration file] [-l load calibration] [-v verbose]\n\r");
+       exit(-1);
+}
+
+void InitFTCC(TFTCConfiguration *pFTCC)
+{
+       pFTCC->nCalibrationTime = 4000;
+
+       pFTCC->bVerbose = false;
+       pFTCC->bLoadCalibration = false;
+       pFTCC->nConfiguration = 0;
+       pFTCC->nConfigurationCalibration = 1;
+       
+       pFTCC->nSpkTMax = SPK_T_MAX;
+       pFTCC->nSpkReTolPer = SPK_RE_TOL_PER;
+       pFTCC->nSpkReAlpha = SPK_RE_ALPHA;
+       
+       pFTCC->nPPC3_Re0 = PPC3_RE0;
+       pFTCC->nPPC3_RTV = PPC3_RTV;
+       pFTCC->nPPC3_RTM = PPC3_RTM;
+       pFTCC->nPPC3_RTVA = PPC3_RTVA;
+       pFTCC->nPPC3_SysGain = PPC3_SYSGAIN;
+       pFTCC->nPPC3_DevNonlinPer = PPC3_DEV_NONLIN_PER;
+       pFTCC->nPPC3_DeltaTLimit = PPC3_DELTA_T_LIMIT;
+       pFTCC->nFSRate = FS_RATE;
+       
+       pFTCC->nDevAAddr = 0x98;
+       pFTCC->nDevBAddr = 0x9a;
+}
+
+unsigned int SkipCharacter(char *pData, char cCharacter, unsigned int nSize)
+{
+       unsigned int nRIndex;
+       unsigned int nWIndex = 0;
+
+       for (nRIndex = 0; nRIndex < nSize; nRIndex++)
+               if (pData[nRIndex] != cCharacter) pData[nWIndex++] = pData[nRIndex];
+
+       return nWIndex;
+}
+
+unsigned int RemoveComments(char *pData, char cCharacter, unsigned int nSize)
+{
+       unsigned int nRIndex;
+       unsigned int nWIndex = 0;
+
+       for (nRIndex = 0; nRIndex < nSize; nRIndex++)
+       {
+               if (pData[nRIndex] == cCharacter)
+                       while ((nRIndex < nSize) && (pData[nRIndex] != '\r')) nRIndex++;
+               pData[nWIndex++] = pData[nRIndex];
+       }
+
+       return nWIndex;
+}
+
+void ReadValue(TFTCConfiguration *pFTCC, char *pLine, char *pValue)
+{
+       if (!strcmp(pLine, "CALIBRATION_TIME")) {pFTCC->nCalibrationTime = atoi(pValue); return;};
+       if (!strcmp(pLine, "CONFIGURATION")) {pFTCC->nConfiguration = atoi(pValue); return;};
+       if (!strcmp(pLine, "CONFIGURATION_CALIBRATION")) {pFTCC->nConfigurationCalibration = atoi(pValue); return;};
+       if (!strcmp(pLine, "SPK_T_MAX")) {pFTCC->nSpkTMax = atof(pValue); return;};
+       if (!strcmp(pLine, "SPK_RE_TOL_PER")) {pFTCC->nSpkReTolPer = atof(pValue); return;};
+       if (!strcmp(pLine, "SPK_RE_ALPHA")) {pFTCC->nSpkReAlpha = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_RE0")) {pFTCC->nPPC3_Re0 = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_RTV")) {pFTCC->nPPC3_RTV = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_RTM")) {pFTCC->nPPC3_RTM = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_RTVA")) {pFTCC->nPPC3_RTVA = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_SYSGAIN")) {pFTCC->nPPC3_SysGain = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_DEV_NONLIN_PER")) {pFTCC->nPPC3_DevNonlinPer = atof(pValue); return;};
+       if (!strcmp(pLine, "PPC3_DELTA_T_LIMIT")) {pFTCC->nPPC3_DeltaTLimit = atof(pValue); return;};
+       if (!strcmp(pLine, "FS_RATE")) {pFTCC->nFSRate = atoi(pValue); return;};
+       if (!strcmp(pLine, "PPC3_DELTA_T_LIMIT")) {pFTCC->nPPC3_DeltaTLimit = atof(pValue); return;};
+       if (!strcmp(pLine, "DEV_A_ADDR")) {pFTCC->nDevAAddr = atoi(pValue); return;};
+       if (!strcmp(pLine, "DEV_B_ADDR")) {pFTCC->nDevBAddr = atoi(pValue); return;};
+}
+
+void ftcc_print(TFTCConfiguration *pFTCC)
+{
+       printf("factorytest configuration: \n\r");
+
+       printf("  CALIBRATION_TIME   = %d\n\r", pFTCC->nCalibrationTime);
+       printf("  CONFIGURATION             = %d\n\r", pFTCC->nConfiguration);
+       printf("  CONFIGURATION_CALIBRATION = %d\n\r\n\r", pFTCC->nConfigurationCalibration);
+       
+       printf("  SPK_T_MAX      = %2.2f\n\r", pFTCC->nSpkTMax);
+       printf("  SPK_RE_TOL_PER = %2.2f\n\r", pFTCC->nSpkReTolPer);
+       printf("  SPK_RE_ALPHA   = %2.4f\n\r\n\r", pFTCC->nSpkReAlpha);
+       
+       printf("  PPC3_RE0            = %2.2f\n\r", pFTCC->nPPC3_Re0);
+       printf("  PPC3_RTV            = %2.2f\n\r", pFTCC->nPPC3_RTV);
+       printf("  PPC3_RTM            = %2.2f\n\r", pFTCC->nPPC3_RTM);
+       printf("  PPC3_RTVA           = %2.2f\n\r", pFTCC->nPPC3_RTVA);
+       printf("  PPC3_SYSGAIN        = %2.2f\n\r", pFTCC->nPPC3_SysGain);
+       printf("  PPC3_DEV_NONLIN_PER = %2.2f\n\r", pFTCC->nPPC3_DevNonlinPer);
+       printf("  PPC3_DELTA_T_LIMIT  = %2.2f\n\r\n\r", pFTCC->nPPC3_DeltaTLimit);
+       
+       printf("  FS_RATE = %d\n\r\n\r", pFTCC->nFSRate);
+}
+
+int ftcc_parse(TFTCConfiguration *pFTCC, char *pData, unsigned int nSize)
+{
+       unsigned int nRIndex = 0;
+       char *pLine;
+       char *pEqual;
+       double nTest;
+
+       nSize = SkipCharacter(pData, ' ', nSize);
+       nSize = RemoveComments(pData, ';', nSize);
+
+       pData[nSize] = 0;
+
+       pLine = strtok(pData, "\n\r");
+
+//     printf("ftcc_parse: pData = %s\n\r", pData);
+
+//     printf("ftcc_parse: size = %d, pLine = 0x%08x\n\r", nSize, pLine);
+       while (pLine)
+       {
+//             printf("ftcc_parse: pLine = 0x%08x\n\r", pLine);
+               if (pLine[0])
+               {
+                       printf("Line = %s\n\r", pLine);
+                       pEqual = strstr(pLine, "=");
+                       if ((pEqual) && (strlen(pEqual) > 1))
+                       {
+                               pEqual[0] = 0;
+                               ReadValue(pFTCC, pLine, pEqual + 1);
+                               pEqual[0] = '=';
+                       }
+               }
+               pLine = strtok(NULL, "\n\r");
+       }
+       
+       return 0;
+}
+
+void LoadFTCC(char *pFileName, TFTCConfiguration *pFTCC)
+{
+       struct stat st;
+       char *pData;
+       int nFile;
+       
+//     printf("LoadFTCC: %s\n\r", pFileName);
+
+       if (stat(pFileName, &st) < 0) ExitWithHint("configuration file doesn't exist");
+
+       pData = malloc(st.st_size);
+       if (!pData) ExitWithHint("cannot allocate memory for configuation file");
+
+    nFile = open(pFileName, O_RDONLY);
+       if (nFile < 0) ExitWithHint("cannot open configuration file"); 
+
+       read(nFile, pData, st.st_size);
+       close(nFile);
+
+       ftcc_parse(pFTCC, pData, st.st_size); 
+
+       free(pData);
+}
+
+int main(int argc, char *argv[])
+{
+       double nTemp = 20.0;
+       int nArg = 1;
+       bool bValidArg;
+       char pHint[256];
+       TFTCConfiguration sFTCC;
+
+       printf("\n\rTI TAS2555 factory test calibration sequence V1.0\n\r");
+
+       InitFTCC(&sFTCC);
+//     printf("argc = %d\n\r", argc);
+       while (nArg < argc)
+       {
+//             printf("argv[%d] = %s: ", nArg, argv[nArg]);
+               bValidArg = false;
+               if (!strcmp(argv[nArg], "-t"))
+               {
+                       printf("nArg = %d, argc = %d\n\r", nArg, argc);
+                       if (argc <= (nArg + 1)) ExitWithHint("temperature parameter is missing");
+                       nTemp = atof(argv[nArg + 1]);
+                       nArg++;
+                       bValidArg = true;
+               }
+
+               if (!strcmp(argv[nArg], "-c"))
+               {
+//                     printf("found configuration file argument\n\r");
+                       if (argc <= (nArg + 1)) ExitWithHint("configuration file name is missing");
+                       LoadFTCC(argv[nArg + 1], &sFTCC);
+                       nArg++;
+                       bValidArg = true;
+               }
+
+               if (!strcmp(argv[nArg], "-v"))
+               {
+                       sFTCC.bVerbose = true;
+                       bValidArg = true;
+               }
+
+               if (!strcmp(argv[nArg], "-l"))
+               {
+                       sFTCC.bLoadCalibration = true;
+                       bValidArg = true;
+               }
+
+               if (!bValidArg)
+               {
+                       sprintf(pHint, "don't know argument %s", argv[nArg]);
+                       ExitWithHint(pHint);
+               }
+               nArg++;
+       }
+
+       if (sFTCC.bVerbose) 
+       {
+               printf("\n\rambient temperature = %2.1f\n\r", nTemp);
+               ftcc_print(&sFTCC);
+       }
+       tas2557_ftc(nTemp, &sFTCC);
+       return 0;
+}
diff --git a/lib/Android.mk b/lib/Android.mk
new file mode 100755 (executable)
index 0000000..9b2cff6
--- /dev/null
@@ -0,0 +1,10 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libftc
+LOCAL_SRC_FILES_32 := libftc32.a
+LOCAL_SRC_FILES_64 := libftc64.a
+LOCAL_MULTILIB := both
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_SUFFIX := .a
+include $(BUILD_PREBUILT)
\ No newline at end of file
diff --git a/lib/libftc32.a b/lib/libftc32.a
new file mode 100755 (executable)
index 0000000..9565057
Binary files /dev/null and b/lib/libftc32.a differ
diff --git a/lib/libftc64.a b/lib/libftc64.a
new file mode 100755 (executable)
index 0000000..a9fc383
Binary files /dev/null and b/lib/libftc64.a differ
diff --git a/speaker.ftcfg b/speaker.ftcfg
new file mode 100755 (executable)
index 0000000..30b2e6e
--- /dev/null
@@ -0,0 +1,29 @@
+\r
+; TAS2557 Factory Test and Calibration Configuration File\r
+; -----------------------------------------------------------------------------\r
+; PPC3 File: example.ppc3\r
+; DDC Name: N48M1V2\r
+; Comments: [Write Comments Here]\r
+\r
+; FTC Settings\r
+CALIBRATION_TIME          = 6000     ; Duration (in ms) of calibration phase\r
+CONFIGURATION             = 0        ; Refer to documentation\r
+CONFIGURATION_CALIBRATION = 2        ; Refer to documentation\r
+DEV_A_ADDR                               = 98           ; I2C slave write addr for device A\r
+DEV_B_ADDR                               = 9a       ; I2C slave write addr for device B\r
+\r
+; Obtained from Speaker Manufacturer\r
+SPK_T_MAX                 = 80       ; Speaker Maximum Temperature (C)\r
+SPK_RE_TOL_PER            = 10       ; Re +/- tolerance (%)\r
+SPK_RE_ALPHA              = 0.0039   ; Temperature coefficient alpha (1/K)\r
+\r
+; Obtained from PurePath Console 3 (PPC3)\r
+PPC3_RE0                  = 7.49     ; Re0 (ohm)\r
+PPC3_RTV                  = 44.9     ; Rtv (K/W)\r
+PPC3_RTM                  = 80.7     ; Rtm  (K/W)\r
+PPC3_RTVA                 = 1723     ; Rtva  (K/W)\r
+PPC3_SYSGAIN              = 9.35     ; System Gain (V/FS)\r
+PPC3_DEV_NONLIN_PER       = 1.5      ; Device Non-linearity (%)\r
+PPC3_DELTA_T_LIMIT        = 60       ; Delta Thermal Limit (C)\r
+FS_RATE                   = 48000    ; TAS2555 Sample Rate\r
+\r
diff --git a/system.c b/system.c
new file mode 100755 (executable)
index 0000000..18fc3d9
--- /dev/null
+++ b/system.c
@@ -0,0 +1,80 @@
+/*
+** =============================================================================
+** Copyright (c) 2016  Texas Instruments Inc.
+**
+** 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; version 2.
+**
+** 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, write to the Free Software Foundation, Inc., 51 Franklin
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**
+** File:
+**     system.c
+**
+** Description:
+**     system functions for TAS2555 factory test program
+**
+** =============================================================================
+*/
+
+#include "system.h"
+
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+pid_t sys_play_wav(char * pFile, char * pMode)
+{
+       pid_t nProcess;
+       int nStatus, nTimeout;
+       char *pArgs[] = {AUDIO_PLAYER, pFile, NULL};
+       char *pEnv[] = {NULL};
+
+       if (0 == (nProcess = fork()))
+       {
+               if (execve(AUDIO_PLAYER, pArgs, pEnv) == -1)
+               {
+                       printf("factorytest: Can't play %s. Please install %s. \n\r", pFile, AUDIO_PLAYER);
+                       exit(-1);
+               }
+       }
+
+       sys_delay(500);
+
+       printf("factorytest: Started playback of %s\n\r", pFile);
+       
+       return nProcess;  
+}
+
+extern void sys_stop_wav(pid_t nProcess)
+{
+       char *pEnv[] = {NULL};
+
+       printf("factorytest: Stop playback.\n\r");
+
+       kill(nProcess, SIGKILL);
+}
+
+extern void sys_delay(uint32_t delay_ms)
+{
+       usleep(delay_ms * 1000);
+}
+
+extern double sys_get_ambient_temp(void)
+{
+       return 0.0;
+}
+
+extern int sys_is_valid(char * pFile)
+{
+       return 0;
+}
+
diff --git a/system.h b/system.h
new file mode 100755 (executable)
index 0000000..bad47c1
--- /dev/null
+++ b/system.h
@@ -0,0 +1,42 @@
+/*\r
+** =============================================================================\r
+** Copyright (c) 2016  Texas Instruments Inc.\r
+**\r
+** This program is free software; you can redistribute it and/or modify it under\r
+** the terms of the GNU General Public License as published by the Free Software \r
+** Foundation; version 2.\r
+**\r
+** This program is distributed in the hope that it will be useful, but WITHOUT\r
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
+**\r
+** You should have received a copy of the GNU General Public License along with\r
+** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+**\r
+** File:\r
+**     system.h\r
+**\r
+** Description:\r
+**     header file for system.c\r
+**\r
+** =============================================================================\r
+*/\r
+\r
+#ifndef SYSTEM_H_\r
+#define SYSTEM_H_\r
+\r
+#include <stdint.h>\r
+#include <sys/types.h>\r
+\r
+#define AUDIO_PLAYER "/system/bin/tinyplay"\r
+#define AUDIO_MIXER "/system/bin/tinymix"\r
+\r
+// Hypothetical System Functions\r
+extern pid_t sys_play_wav(char * pFile, char * pMode);\r
+extern void sys_stop_wav(pid_t nProcess);\r
+extern void sys_delay(uint32_t delay_ms);\r
+extern double sys_get_ambient_temp(void);\r
+extern int sys_is_valid(char * pFile);\r
+\r
+#endif /* SYSTEM_H_ */\r
diff --git a/tas2557.c b/tas2557.c
new file mode 100755 (executable)
index 0000000..946a9f1
--- /dev/null
+++ b/tas2557.c
@@ -0,0 +1,337 @@
+/*
+** =============================================================================
+** Copyright (c) 2016  Texas Instruments Inc.
+**
+** 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; version 2.
+**
+** 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, write to the Free Software Foundation, Inc., 51 Franklin
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**
+** File:
+**     tas2555.c
+**
+** Description:
+**     functions for configurating TAS2555 Android device
+**
+** =============================================================================
+*/
+
+#include "tas2557.h"
+#include "system.h"
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+
+#define TILOAD_NODE "/dev/tiload_node"
+
+static int gTILoad = 0;
+static int gBinFile = 0;
+
+#define MAX_BIN_SIZE 2048
+static char gpBin[MAX_BIN_SIZE];
+static unsigned int gnBinIndex = 0;
+static unsigned int gnBinBlockIndex = 0;
+static char gpDevABlock[MAX_BIN_SIZE/2];
+static unsigned int gnDevABlockIndex = 0;
+static char gpDevBBlock[MAX_BIN_SIZE/2];
+static unsigned int gnDevBBlockIndex = 0;
+static unsigned char gnDevA;
+static unsigned char gnDevB;
+static unsigned char gnDev;
+
+static void tas2557_check_node(void);
+
+void tas2557_mixer_command(char *pCommand, int nData)
+{
+       char *pMixer[] = {AUDIO_MIXER, pCommand, "0", NULL};
+       char *pEnv[] = {NULL};
+
+       char pData[16];
+
+       printf("TAS2555 mixer command %s = %d.\n\r", pCommand, nData);
+
+       sprintf(pData, "%d", nData);
+       pMixer[2] = pData;
+       
+       if (0 == (fork()))
+       {
+               if (execve(AUDIO_MIXER, pMixer, pEnv) == -1)
+               {
+                       printf("factorytest: Can't find mixer. Please install %s. \n\r", AUDIO_MIXER);
+                       exit(-1);
+               }
+       }
+
+       sys_delay(500);
+}
+
+void tas2557_load_configuration(int nConfiguration)
+{
+       tas2557_check_node();
+       
+       ioctl(gTILoad, TILOAD_IOCTL_SET_CONFIG, &nConfiguration);
+       sys_delay(500);
+}
+
+void tas2557_load_calibration(int nCalibration)
+{
+       tas2557_check_node();
+       
+       ioctl(gTILoad, TILOAD_IOCTL_SET_CALIBRATION, &nCalibration);
+       sys_delay(500);
+}
+
+static void tas2557_check_node(void)
+{
+       if (gTILoad) return;
+
+       gTILoad = open(TILOAD_NODE, O_RDWR);
+
+       if (gTILoad < 0)
+       {
+               printf("factorytest: Can't find tiload. Please create %s. \n\r", TILOAD_NODE);
+               exit(-1);
+       }
+
+       printf("factorytest: %s handle = %d\n\r", TILOAD_NODE, gTILoad);
+}
+
+uint32_t tas2557_coeff_read(uint8_t book, uint8_t page, uint8_t reg)
+{
+       unsigned char pPageZero[] = {0x00, 0x00};
+       unsigned char pBook[] = {0x7F, book};
+       unsigned char pPage[] = {0x00, page};
+       unsigned char pData[] = {reg, 0x00, 0x00, 0x00, 0x00};
+
+       tas2557_check_node();
+
+       write(gTILoad, pPageZero, 2);
+       write(gTILoad, pBook, 2);
+       write(gTILoad, pPage, 2);
+       read(gTILoad, pData, 4);
+
+       return ((pData[0] << 24) | (pData[1] << 16) | (pData[2] << 8) | (pData[3]));
+}
+
+uint32_t tas2557_switch_device(uint8_t i2cslave)
+{
+       tas2557_check_node();
+
+       gnDev = i2cslave;
+       
+       ioctl(gTILoad, TILOAD_IOCTL_SET_CHL, &i2cslave);
+       
+       return 0;
+}
+
+void tas2557_coeff_write(uint8_t book, uint8_t page, uint8_t reg, uint32_t data)
+{
+       unsigned int nByte;
+
+       if (gBinFile) // if the bin file is open, write the coefficients to the bin file
+       {
+               if(gnDev == gnDevA){
+                       unsigned int index = gnDevABlockIndex*4;
+                       gpDevABlock[index] = 0;
+                       gpDevABlock[index + 1] = 4;
+                       gpDevABlock[index + 2] = 0x85;
+                       gpDevABlock[index + 4] = book;
+                       gpDevABlock[index + 5] = page;
+                       gpDevABlock[index + 6] = reg;
+                       
+                       for (nByte = 0; nByte < 4; nByte++)
+                       {
+                               gpDevABlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
+                       }
+                       
+                       gnDevABlockIndex += 2;                  
+               }
+               else if(gnDev == gnDevB)
+               {
+                       unsigned int index = gnDevBBlockIndex*4;
+                       gpDevBBlock[index] = 0;
+                       gpDevBBlock[index + 1] = 4;
+                       gpDevBBlock[index + 2] = 0x85;
+                       gpDevBBlock[index + 4] = book;
+                       gpDevBBlock[index + 5] = page;
+                       gpDevBBlock[index + 6] = reg;
+                       
+                       for (nByte = 0; nByte < 4; nByte++)
+                       {
+                               gpDevBBlock[index + 7 + nByte] = (data >> ((3 - nByte) * 8)) & 0xFF;
+                       }
+                       
+                       gnDevBBlockIndex += 2;  
+               }               
+       }
+       else
+       {
+               unsigned char pPageZero[] = {0x00, 0x00};
+               unsigned char pBook[] = {0x7F, book};
+               unsigned char pPage[] = {0x00, page};
+               unsigned char pData[] = {reg, (data & 0xFF000000) >> 24, (data & 0x00FF0000) >> 16, (data & 0x0000FF00) >> 8, data & 0x000000FF};
+
+               tas2557_check_node();
+
+               write(gTILoad, pPageZero, 2);
+               write(gTILoad, pBook, 2);
+               write(gTILoad, pPage, 2);
+               write(gTILoad, pData, 5);
+
+               pBook[1] = 0x8C;
+               pPage[1] = 0x19;
+
+               pData[0] = 0x7C;
+               pData[1] = 0x00;
+               pData[2] = 0x00;
+               pData[3] = 0x00;
+               pData[4] = 0x01;
+
+               write(gTILoad, pPageZero, 2);
+               write(gTILoad, pBook, 2);
+               write(gTILoad, pPage, 2);
+               write(gTILoad, pData, 5);
+       }
+}
+
+void tas2557_save_cal(double dev_a_re, uint32_t dev_a_rms_pow, uint32_t dev_a_t_limit, 
+       double dev_b_re, uint32_t dev_b_rms_pow, uint32_t dev_b_t_limit, 
+       double t_cal,  char * pFileName)
+{
+       printf("TAS2557 calibration values:\n\r");
+       
+       printf("    DevA Re = %1.2f Ohm\n\r", dev_a_re);
+       printf("    DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
+       printf("    DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
+       printf("    DevB Re = %1.2f Ohm\n\r", dev_b_re);
+       printf("    DevB rms_pow       = 0x%08X\n\r", dev_b_rms_pow);
+       printf("    DevB t_limit       = 0x%08X\n\r", dev_b_t_limit);
+       
+       FILE *pFile = fopen(pFileName, "w+");
+       
+       fprintf(pFile, "DevA Re = %1.2f\n\r", dev_a_re);
+       fprintf(pFile, "DevA rms_pow       = 0x%08X\n\r", dev_a_rms_pow);
+       fprintf(pFile, "DevA t_limit       = 0x%08X\n\r", dev_a_t_limit);
+       fprintf(pFile, "DevB Re = %1.2f\n\r", dev_b_re);
+       fprintf(pFile, "DevB rms_pow       = 0x%08X\n\r", dev_b_rms_pow);
+       fprintf(pFile, "DevB t_limit       = 0x%08X\n\r", dev_b_t_limit);       
+       fprintf(pFile, "Ambient temperature = %2.2f\n\r\n\r", t_cal);
+
+       fclose(pFile);
+}
+
+void tas2557_open_bin(char * pFileName, unsigned int nConfiguration, 
+       unsigned char dev_a, unsigned char dev_b)
+{
+       gnDevA = dev_a;
+       gnDevB = dev_b;
+       
+       gBinFile = open(pFileName, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IROTH | S_IWOTH);
+
+       memset(gpBin, 0, MAX_BIN_SIZE);
+       memset(gpDevABlock, 0, MAX_BIN_SIZE/2);
+       gnDevABlockIndex = 0;
+       memset(gpDevBBlock, 0, MAX_BIN_SIZE/2);
+       gnDevBBlockIndex = 0;
+       
+       gpBin[3] = '2';
+       gpBin[2] = '5';
+       gpBin[1] = '5';
+       gpBin[0] = '5';
+
+       strcpy(&gpBin[24], "Calibration Data File");
+       strcpy(&gpBin[24 + 64], "Calibration Data File for TAS2555");
+
+       gnBinIndex += 24 + 64 + strlen(&gpBin[24 + 64]) + 1;
+       
+       gnBinIndex +=
+               4 +     //device family index
+               4 +     //device index
+               2 +     //num PLL index
+               0 +     //array PLL index
+               2 +     //num programs index
+               0 +     //array programs index
+               2 +     //num configurations index
+               0;      //array configurations index
+       
+       gpBin[gnBinIndex++] = 0x00;
+       gpBin[gnBinIndex++] = 0x01; // one calibration data block
+
+       strcpy(&gpBin[gnBinIndex], "Calibration Data");
+       gnBinIndex += 64;
+       strcpy(&gpBin[gnBinIndex], "Calibration Data for TAS2555");
+       gnBinIndex += strlen(&gpBin[gnBinIndex]) + 1;
+       gpBin[gnBinIndex++] = 0x00; // compatible program = smart amp (index 0)
+       gpBin[gnBinIndex++] = nConfiguration; // compatible configuration
+       
+       gpDevABlock[0] = 0;
+       gpDevABlock[1] = 0;
+       gpDevABlock[2] = 0;
+       gpDevABlock[3] = 0x03;  //o     COEFF_DEVICE_A – 0x03
+       gnDevABlockIndex = 2;
+       
+       gpDevBBlock[0] = 0;
+       gpDevBBlock[1] = 0;
+       gpDevBBlock[2] = 0;
+       gpDevBBlock[3] = 0x0a;  //o     COEFF_DEVICE_B – 0x0a
+       gnDevBBlockIndex = 2;
+}
+
+void tas2557_close_bin(void)
+{
+       unsigned int nCommands;
+       unsigned char pCommit[] =
+       {
+               0x00, 0x04, 0x85, 0x00,
+               0x8C, 0x19, 0x7C, 0x00,
+               0x00, 0x00, 0x01, 0x00
+       };      
+       
+       // write the commit sequence
+       memcpy(&gpDevABlock[gnDevABlockIndex*4], pCommit, 12);
+       gnDevABlockIndex += 3;
+       
+       memcpy(&gpDevBBlock[gnDevBBlockIndex*4], pCommit, 12);
+       gnDevBBlockIndex += 3;
+       
+       // write number of commands for calibration block
+       gpDevABlock[4] = ((gnDevABlockIndex-2) & 0xFF000000) >> 24;
+       gpDevABlock[5] = ((gnDevABlockIndex-2) & 0x00FF0000) >> 16;
+       gpDevABlock[6] = ((gnDevABlockIndex-2) & 0x0000FF00) >> 8;
+       gpDevABlock[7] = ((gnDevABlockIndex-2) & 0x000000FF);
+               
+       gpDevBBlock[4] = ((gnDevBBlockIndex-2) & 0xFF000000) >> 24;
+       gpDevBBlock[5] = ((gnDevBBlockIndex-2) & 0x00FF0000) >> 16;
+       gpDevBBlock[6] = ((gnDevBBlockIndex-2) & 0x0000FF00) >> 8;
+       gpDevBBlock[7] = ((gnDevBBlockIndex-2) & 0x000000FF);
+       
+       memcpy(&gpBin[gnBinIndex], gpDevABlock, gnDevABlockIndex*4);
+       gnBinIndex += (gnDevABlockIndex*4);
+       
+       memcpy(&gpBin[gnBinIndex], gpDevBBlock, gnDevBBlockIndex*4);
+       gnBinIndex += (gnDevBBlockIndex*4);
+       
+       // write bin file size
+       gpBin[4] = (gnBinIndex & 0xFF000000) >> 24;
+       gpBin[5] = (gnBinIndex & 0x00FF0000) >> 16;
+       gpBin[6] = (gnBinIndex & 0x0000FF00) >> 8;
+       gpBin[7] = (gnBinIndex & 0x000000FF);
+
+       write(gBinFile, gpBin, gnBinIndex);
+       close(gBinFile);
+
+       gBinFile = 0;
+}
diff --git a/tas2557.h b/tas2557.h
new file mode 100755 (executable)
index 0000000..c143336
--- /dev/null
+++ b/tas2557.h
@@ -0,0 +1,52 @@
+/*\r
+** =============================================================================\r
+** Copyright (c) 2016  Texas Instruments Inc.\r
+**\r
+** This program is free software; you can redistribute it and/or modify it under\r
+** the terms of the GNU General Public License as published by the Free Software \r
+** Foundation; version 2.\r
+**\r
+** This program is distributed in the hope that it will be useful, but WITHOUT\r
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
+**\r
+** You should have received a copy of the GNU General Public License along with\r
+** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+**\r
+** File:\r
+**     tas2557.h\r
+**\r
+** Description:\r
+**     header file for tas2557.c\r
+**\r
+** =============================================================================\r
+*/\r
+\r
+#ifndef TAS2557_H_\r
+#define TAS2557_H_\r
+\r
+#include <stdint.h>\r
+\r
+#define TILOAD_IOC_MAGIC   0xE0\r
+\r
+#define CONFIGURATION 0\r
+#define CONFIGURATION_CALIBRATION 2\r
+\r
+#define TILOAD_IOCTL_SET_CHL                   _IOW(TILOAD_IOC_MAGIC, 5, int)\r
+#define TILOAD_IOCTL_SET_CONFIG                _IOW(TILOAD_IOC_MAGIC, 6, int)\r
+#define TILOAD_IOCTL_SET_CALIBRATION   _IOW(TILOAD_IOC_MAGIC, 7, int)\r
+\r
+extern void tas2557_load_configuration(int nConfiguration);\r
+extern void tas2557_load_calibration(int nCalibration);\r
+extern uint32_t tas2557_switch_device(uint8_t i2cslave);\r
+extern uint32_t tas2557_coeff_read(uint8_t book, uint8_t page, uint8_t reg);\r
+extern void tas2557_coeff_write(uint8_t book, uint8_t page, uint8_t reg, uint32_t data);\r
+extern void tas2557_save_cal(double dev_a_re, uint32_t dev_a_rms_pow, uint32_t dev_a_t_limit, \r
+       double dev_b_re, uint32_t dev_b_rms_pow, uint32_t dev_b_t_limit, \r
+       double t_cal,  char * pFileName);\r
+extern void tas2557_open_bin(char * pFileName, unsigned int nConfiguration, \r
+       unsigned char dev_a, unsigned char dev_b);\r
+extern void tas2557_close_bin(void);\r
+\r
+#endif /* TAS2557_H_ */\r
diff --git a/tas2557_ftc.h b/tas2557_ftc.h
new file mode 100755 (executable)
index 0000000..3a94b0a
--- /dev/null
@@ -0,0 +1,62 @@
+/*\r
+** =============================================================================\r
+** Copyright (c) 2016  Texas Instruments Inc.\r
+**\r
+** This program is free software; you can redistribute it and/or modify it under\r
+** the terms of the GNU General Public License as published by the Free Software \r
+** Foundation; version 2.\r
+**\r
+** This program is distributed in the hope that it will be useful, but WITHOUT\r
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
+**\r
+** You should have received a copy of the GNU General Public License along with\r
+** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+**\r
+** File:\r
+**     tas2557_ftc.h\r
+**\r
+** Description:\r
+**     header file for tas2557_ftc.c\r
+**\r
+** =============================================================================\r
+*/\r
+\r
+#ifndef TAS2557_FTC_H_\r
+#define TAS2557_FTC_H_\r
+\r
+#include <stdint.h>\r
+#include <stdbool.h>\r
+\r
+typedef struct\r
+{\r
+       bool bVerbose;\r
+       bool bLoadCalibration;\r
+\r
+       unsigned int nCalibrationTime;\r
+\r
+       bool bFTCBypass;\r
+       unsigned int nConfiguration;\r
+       unsigned int nConfigurationCalibration;\r
+       \r
+       double nSpkTMax;\r
+       double nSpkReTolPer;\r
+       double nSpkReAlpha;\r
+       \r
+       double nPPC3_Re0;\r
+       double nPPC3_RTV;\r
+       double nPPC3_RTM;\r
+       double nPPC3_RTVA;\r
+       double nPPC3_SysGain;\r
+       double nPPC3_DevNonlinPer;\r
+       double nPPC3_DeltaTLimit;\r
+       unsigned int nFSRate;\r
+       \r
+       unsigned char nDevAAddr;\r
+       unsigned char nDevBAddr;\r
+} TFTCConfiguration;\r
+\r
+extern uint32_t tas2557_ftc(double t_cal, TFTCConfiguration *pFTCC);\r
+\r
+#endif /* TAS2557_FTC_H_ */\r
diff --git a/tas2557dm_ftc.c b/tas2557dm_ftc.c
new file mode 100755 (executable)
index 0000000..dd935f0
--- /dev/null
@@ -0,0 +1,134 @@
+/*\r
+** =============================================================================\r
+** Copyright (c) 2016  Texas Instruments Inc.\r
+**\r
+** This program is free software; you can redistribute it and/or modify it under\r
+** the terms of the GNU General Public License as published by the Free Software \r
+** Foundation; version 2.\r
+**\r
+** This program is distributed in the hope that it will be useful, but WITHOUT\r
+** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
+** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.\r
+**\r
+** You should have received a copy of the GNU General Public License along with\r
+** this program; if not, write to the Free Software Foundation, Inc., 51 Franklin\r
+** Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+**\r
+** File:\r
+**     tas2557_ftc.c\r
+**\r
+** Description:\r
+**     factory test program for TAS2557 Android devices\r
+**\r
+** =============================================================================\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <stdint.h>\r
+#include <math.h>\r
+#include <sys/types.h>\r
+\r
+#include "system.h"\r
+#include "tas2557.h"        // TAS2557 Driver\r
+#include "tas2557_ftc_lib.h"    \r
+#include "tas2557_ftc.h"    // TAS2557 Factory Test and Calibration Tool\r
+\r
+#define PI                   3.14159\r
+\r
+TFTCConfiguration *gpFTCC;\r
+\r
+// -----------------------------------------------------------------------------\r
+// tas2557_ftc\r
+// -----------------------------------------------------------------------------\r
+// Description:\r
+//      Obtains Re, f0, Q and T_cal from the speaker. This only needs to be\r
+//      executed once during production line test.\r
+// -----------------------------------------------------------------------------\r
+uint32_t tas2557_ftc(double t_cal, TFTCConfiguration *pFTCC)\r
+{\r
+    double dev_a_re = pFTCC->nPPC3_Re0;   // Default Re\r
+    uint32_t dev_a_prm_pow = 0;           // Total RMS power coefficient\r
+    uint32_t dev_a_prm_tlimit = 0;        // Delta temperature limit coefficient\r
+    double dev_b_re = pFTCC->nPPC3_Re0;   // Default Re\r
+    uint32_t dev_b_prm_pow = 0;           // Total RMS power coefficient\r
+    uint32_t dev_b_prm_tlimit = 0;        // Delta temperature limit coefficient       \r
+       \r
+    uint32_t result = 0;\r
+    pid_t nPlaybackProcess;\r
+\r
+    gpFTCC = pFTCC;\r
+\r
+    // STEP 1: Load TAS2555 calibration configuration\r
+    tas2557_load_configuration(gpFTCC->nConfigurationCalibration);\r
+\r
+    // STEP 2: Play calibration signal\r
+    nPlaybackProcess = sys_play_wav("silense.wav", "loop");\r
+\r
+       // STEP 3: Play calibration signal\r
+       tas2557_switch_device(gpFTCC->nDevAAddr);\r
+    tas2557_ftc_start();\r
+       tas2557_switch_device(gpFTCC->nDevBAddr);\r
+       tas2557_ftc_start();\r
+       \r
+    // STEP 4: Wait for algorithm to converge\r
+    sys_delay(gpFTCC->nCalibrationTime); // Delay \r
+\r
+       \r
+    // STEP 5: Get actual Re from TAS2555\r
+       tas2557_switch_device(gpFTCC->nDevAAddr);\r
+    dev_a_re = get_re(gpFTCC->nPPC3_Re0);\r
+       tas2557_switch_device(gpFTCC->nDevBAddr);\r
+       dev_b_re = get_re(gpFTCC->nPPC3_Re0);\r
+\r
+    // STEP 6: Set temperature limit to target TMAX\r
+       tas2557_switch_device(gpFTCC->nDevAAddr);\r
+    dev_a_prm_pow = calc_prm_pow (dev_a_re, \r
+               gpFTCC->nSpkTMax - t_cal, \r
+               gpFTCC->nPPC3_RTV, \r
+               gpFTCC->nPPC3_RTM, \r
+               gpFTCC->nPPC3_RTVA, \r
+               gpFTCC->nPPC3_SysGain);\r
+    dev_a_prm_tlimit = calc_prm_tlimit(gpFTCC->nSpkTMax - t_cal, \r
+               gpFTCC->nSpkReAlpha, \r
+               gpFTCC->nPPC3_DevNonlinPer, \r
+               gpFTCC->nPPC3_RTV, \r
+               gpFTCC->nPPC3_RTM, \r
+               gpFTCC->nPPC3_RTVA);\r
+    set_re(gpFTCC->nPPC3_Re0, dev_a_re, gpFTCC->nSpkReAlpha);\r
+    set_temp_cal(dev_a_prm_pow, dev_a_prm_tlimit);\r
+       tas2557_switch_device(gpFTCC->nDevBAddr);\r
+    dev_b_prm_pow = calc_prm_pow (dev_b_re, \r
+               gpFTCC->nSpkTMax - t_cal, \r
+               gpFTCC->nPPC3_RTV, \r
+               gpFTCC->nPPC3_RTM, \r
+               gpFTCC->nPPC3_RTVA, \r
+               gpFTCC->nPPC3_SysGain);\r
+    dev_b_prm_tlimit = calc_prm_tlimit(gpFTCC->nSpkTMax - t_cal, \r
+               gpFTCC->nSpkReAlpha, \r
+               gpFTCC->nPPC3_DevNonlinPer, \r
+               gpFTCC->nPPC3_RTV, \r
+               gpFTCC->nPPC3_RTM, \r
+               gpFTCC->nPPC3_RTVA);\r
+    set_re(gpFTCC->nPPC3_Re0, dev_b_re, gpFTCC->nSpkReAlpha);\r
+    set_temp_cal(dev_b_prm_pow, dev_b_prm_tlimit);     \r
+    sys_stop_wav(nPlaybackProcess);\r
+\r
+    // STEP 7: Save Re, f0, Q and Cal Temp into a file\r
+    tas2557_save_cal(dev_a_re, dev_a_prm_pow, dev_a_prm_tlimit, \r
+               dev_b_re, dev_b_prm_pow, dev_b_prm_tlimit, \r
+               t_cal, "tas2557_cal.txt");\r
+\r
+    // STEP 8: Save .bin file for TAS2555 driver\r
+       tas2557_open_bin("tas2557_cal.bin", gpFTCC->nConfiguration, gpFTCC->nDevAAddr, gpFTCC->nDevBAddr);\r
+       tas2557_switch_device(gpFTCC->nDevAAddr);\r
+       set_re(gpFTCC->nPPC3_Re0, dev_a_re, gpFTCC->nSpkReAlpha);\r
+       set_temp_cal(dev_a_prm_pow, dev_a_prm_tlimit);\r
+       tas2557_switch_device(gpFTCC->nDevBAddr);\r
+       set_re(gpFTCC->nPPC3_Re0, dev_b_re, gpFTCC->nSpkReAlpha);\r
+       set_temp_cal(dev_b_prm_pow, dev_b_prm_tlimit);  \r
+       tas2557_close_bin();\r
+\r
+       if (gpFTCC->bLoadCalibration) tas2557_load_calibration(0xFF);\r
+\r
+    return result;\r
+}\r