|
AudioScience HPI Version_4.11.
|
/****************************************************************************** $Header: /home/eliot/asi/repo/cvsrepo/Repository/drv/linux/test/asihpitune.c,v 1.47 2011/04/05 10:02:06 as-dxb Exp $ Control tuners on ASI87xx, ASI8821 and ASI892x cards Usage: asihpitune --help ******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <ctype.h> #include <time.h> #ifdef HPI_OS_LINUX #include <unistd.h> #endif #include <getopt.h> #ifdef __APPLE__ #include <hpi/hpi.h> #include <hpi/hpirds.h> #include <hpi/hpidebug.h> #else #include <hpi.h> #include <hpirds.h> #include <hpidebug.h> #endif #define verbose_printf if (verbose) printf typedef struct { uint16_t wControlType; // HPI_CONTROL_METER, _VOLUME etc uint16_t wSrcNodeType; uint16_t wSrcNodeIndex; uint16_t wDstNodeType; uint16_t wDstNodeIndex; } hpi_control_t; static char *hpi_control_strings[] = HPI_CONTROL_TYPE_STRINGS; static char *hpi_src_strings[] = HPI_SOURCENODE_STRINGS; static char *hpi_dst_strings[] = HPI_DESTNODE_STRINGS; #define nanosec 1000000 // local protos static void HandleError( hpi_err_t err ); static void HandleErrorComment( char *comment, hpi_err_t err ); static void HandleErrorCommentContinue( char *comment, hpi_err_t err ); static int getch( void ); static void asi_sleep( unsigned int milliseconds ); /* NOTE: indices must match HPI defines for each band */ static char *band_names[HPI_TUNER_BAND_LAST + 1] = { "invalid", "AM", "FM", "NTSC_M", "FM2", "Aux", "PAL_BG", "PAL_I", "PAL_DK", "Secam_L", }; /* Option variables */ static unsigned int dump_mixer = 0; static uint16_t wAdapterIndex = 0; static uint16_t nTunerIndex = 0; static uint16_t nBand = 0; static uint32_t nTunerFrequency = 0; static short wRssMode = -1; static short wRdsMode = -1; static int query_tuner_caps = 0; static int query_tuner_settings = 0; static int verbose = 0; static int rds = 0; static int rds_poll_ms = 1000; static int rds_poll_loops = 100; static short nMux = -1; static struct option long_options[] = { {"adapter", required_argument, 0, 'a'}, {"band", required_argument, 0, 'b'}, {"query-caps", no_argument, 0, 'c'}, {"dump-mixer", no_argument, 0, 'd'}, {"frequency", required_argument, 0, 'f'}, {"rss-mode", required_argument, 0, 'm'}, {"rds-mode", required_argument, 0, 'n'}, {"rds_poll_ms", required_argument, 0, 'p'}, {"rds", optional_argument, 0, 'r'}, {"settings", no_argument, 0, 's'}, {"tuner", required_argument, 0, 't'}, {"verbose", no_argument, 0, 'v'}, {"mux", required_argument, 0, 'x'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; static const char *short_options = "a:b:cdf:m:n:p:r::t:st:vx:h"; static const char *option_help[] = { "<adapter number> to test, default is 0.", "<band> see below for valid options", "Query tuner capabilities.", "Dump list of mixer controls.", "<freq in kHz> tuner frequency", "<mode> Set tuner RSS mode.", "<mode> Set tuner RDS mode.", "<milliseconds> Set RDS polling interval. Default 1000", "[optional loop count] Reads RDS data from the tuner. Default 100 loops", "Read back tuner settings.", "<tuner index> to query or set, default is 0.", "Enable verbose output.", "<n> Set audio out mux to tuner", "Show this text." }; static void help( void ) { int i = 0; printf("\nUsage - asihpitune [options]\n"); while (long_options[i].name != 0) { printf("--%s -%c %s\n", long_options[i].name, (char)(long_options[i].val), option_help[i]); i++; } printf("Valid values for -b option are "); for (i = 1; i <= HPI_TUNER_BAND_LAST; i++) printf("%s, ", band_names[i]); printf("\n"); exit(0); } static void parse_options( int argc, char *argv[] ) { int c; /*********** Parse the command line options ***************/ while (1) { // int this_option_optind = optind ? optind : 1; int option_index = 0; c = getopt_long(argc, argv, short_options, long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case 'a': wAdapterIndex = atoi(optarg); break; case 'b': { int i; for (i = 1; i <= HPI_TUNER_BAND_LAST; i++) if (strcmp(band_names[i], optarg) == 0) nBand = i; if (!nBand) { printf("\n****** Invalid band: %s ******\n", optarg); help(); } query_tuner_settings = 1; } break; case 'c': query_tuner_caps = 1; break; case 'd': dump_mixer = 1; break; case 'f': nTunerFrequency = atoi(optarg); query_tuner_settings = 1; break; case 'm': wRssMode = atoi(optarg); query_tuner_settings = 1; break; case 'n': wRdsMode = atoi(optarg); query_tuner_settings = 1; break; case 'p': rds_poll_ms = atoi(optarg); rds = 1; break; case 'r': rds = 1; if (optarg) rds_poll_loops = atoi(optarg); break; case 's': query_tuner_settings = 1; break; case 't': nTunerIndex = atoi(optarg); break; case 'v': verbose = 1; break; case 'x': nMux = atoi(optarg); break; case '?': case 'h': help(); break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { // printf ("non-option ARGV-elements: "); /* nNumFiles=0; while ((optind < argc) && (nNumFiles < MAX_FILES)) { strcpy( szFile[nNumFiles], argv[optind++] ); printf("File %d is %s\n",nNumFiles,szFile[nNumFiles]); nNumFiles++; } */ } } static void print_mixer_controls(hpi_hsubsys_t *hSubSys, hpi_handle_t hMixer) { uint16_t f; hpi_handle_t hTuner; uint32_t err; for (f = 0; f < 256; f++) { hpi_control_t asihpi_control; err = HPI_MixerGetControlByIndex(hSubSys, hMixer, f, &asihpi_control.wSrcNodeType, &asihpi_control.wSrcNodeIndex, &asihpi_control.wDstNodeType, &asihpi_control.wDstNodeIndex, &asihpi_control.wControlType, // HPI_CONTROL_METER, _VOLUME etc &hTuner); if (err == HPI_ERROR_CONTROL_DISABLED) printf("DISABLED "); else if (err) break; printf("HPI Control %d, %s:%s[%d]->%s[%d]\n", f, hpi_control_strings[asihpi_control.wControlType], hpi_src_strings[asihpi_control.wSrcNodeType - HPI_SOURCENODE_NONE], asihpi_control.wSrcNodeIndex, hpi_dst_strings[asihpi_control.wDstNodeType - HPI_DESTNODE_NONE], asihpi_control.wDstNodeIndex); if (asihpi_control.wControlType == HPI_CONTROL_MULTIPLEXER) { uint16_t l; for (l = 0; l < 256; l++) { err = HPI_Multiplexer_QuerySource(hSubSys, hTuner, l, &asihpi_control. wSrcNodeType, &asihpi_control.wSrcNodeIndex); if (!err) printf("\tSource %d %s[%d]\n", l, hpi_src_strings [asihpi_control.wSrcNodeType - HPI_SOURCENODE_NONE], asihpi_control.wSrcNodeIndex); else break; } } } printf("%d controls found\n\n", f); } /************************************** MAIN ***********************/ int main( int argc, char *argv[] ) { hpi_hsubsys_t *hSubSys; hpi_err_t err = 0; // HPI error uint32_t dwVersion = 0; int numAdapters = 0; uint16_t wVersion; uint32_t dwSerialNumber; uint16_t wType; uint16_t wNumOutStreams; uint16_t wNumInStreams; int i; hpi_handle_t hMixer = 0; hpi_handle_t hTuner = 0, hMux = 0; parse_options(argc, argv); /* */ verbose_printf ("********************************************************************\n"); verbose_printf ("\n** $Id: asihpitune.c,v 1.47 2011/04/05 10:02:06 as-dxb Exp $ **\n"); verbose_printf("\n** HPI test code for tuners **\n"); /* if (argc>1) sscanf(argv[1],"%d",&wAdapterIndex); else { printf("Usage:\n:Dump the mixer map of the adapter: test8700 <adapter index>\n"); printf("Show tuner bands: test8700 <adapter index> <tuner index>\n"); printf("Set a tuner: test8700 <adapter index> <tuner index> <band> <frequency in kHz>\n"); exit (0); } */ /* */ // open subsystem and find adapters verbose_printf ("********************************************************************\n"); printf("HPI_SubSysCreate\n"); hSubSys = HPI_SubSysCreate(); if (hSubSys == NULL) { printf("hSubSys==NULL\n"); exit(1); } err = HPI_SubSysGetVersionEx(hSubSys, &dwVersion); HandleError(err); verbose_printf("HPI_SubSysGetVersionEx=%d.%02d.%02d\n", dwVersion >> 16, (dwVersion >> 8) & 0xff, dwVersion & 0xff); err = HPI_SubSysGetNumAdapters(hSubSys, &numAdapters); HandleError(err); verbose_printf("HPI_SubSysGetNumAdapters NumberAdapters=%d ", numAdapters); for (i = 0; i < numAdapters; i++) { uint32_t dwAdapterIndex; uint16_t wAdapterType; err = HPI_SubSysGetAdapter(hSubSys, i, &dwAdapterIndex, &wAdapterType); verbose_printf("%d=%X\n ", dwAdapterIndex, wAdapterType); } err = HPI_AdapterClose(hSubSys, wAdapterIndex); HandleError(err); verbose_printf("HPI_AdapterClose \n"); // open 1st adapter err = HPI_AdapterOpen(hSubSys, wAdapterIndex); HandleError(err); verbose_printf("HPI_AdapterOpen \n"); err = HPI_AdapterGetInfo(hSubSys, wAdapterIndex, &wNumOutStreams, &wNumInStreams, &wVersion, &dwSerialNumber, &wType); HandleError(err); verbose_printf("HPI_AdapterGetInfo\n"); verbose_printf("Adapter ID=%4X Index=%d NumOutStreams=%d NumInStreams=%d S/N=%d\n\tHw Version %c%d ", wType, wAdapterIndex, wNumOutStreams, wNumInStreams, dwSerialNumber, ((wVersion >> 3) & 0xf) + 'A', // Hw version major wVersion & 0x7 // Hw version minor ); if (verbose) { uint16_t major, minor; err = HPI_AdapterGetProperty(hSubSys, wAdapterIndex, HPI_ADAPTER_PROPERTY_SOFTWARE_VERSION, &major, &minor); HandleError(err); verbose_printf("DSP code version %d.%02d.%02d\n", major >> 8, major & 0xff, minor); } // open the mixer of this adapter err = HPI_MixerOpen(hSubSys, wAdapterIndex, &hMixer); verbose_printf("HPI_MixerOpen: handle=%X\n", hMixer); HandleError(err); printf("\n"); /******** Dump mixer ******/ if (dump_mixer) print_mixer_controls(hSubSys, hMixer); if ((wType & 0xF000) != 0x8000) { printf("Only ASI87xx, ASI8821 and ASI89xx adapters are supported/n"); goto close; } err = HPI_MixerGetControl(hSubSys, hMixer, HPI_SOURCENODE_TUNER, nTunerIndex, 0, 0, HPI_CONTROL_TUNER, &hTuner); HandleErrorComment("Get Tuner Control", err); if (err) goto close; err = HPI_MixerGetControl(hSubSys, hMixer, 0, 0, HPI_DESTNODE_LINEOUT, 0, HPI_CONTROL_MULTIPLEXER, &hMux); HandleErrorComment("Get Mux", err); /******** Mode setting ******/ if (wRssMode >= 0) { err = HPI_Tuner_SetMode(hSubSys, hTuner, HPI_TUNER_MODE_RSS, wRssMode); HandleErrorComment("SetMode RSS", err); } if (wRdsMode >= 0) { err = HPI_Tuner_SetMode(hSubSys, hTuner, HPI_TUNER_MODE_RDS, wRdsMode); HandleErrorComment("SetMode RDS", err); } /******** Mux setting ******/ if (hMux && (nMux >= 0) && (nMux < 8)) { HandleErrorComment("Get mux ctrl", err); err = HPI_Multiplexer_SetSource(hSubSys, hMux, HPI_SOURCENODE_TUNER, nMux); HandleErrorComment("SetMuxSource", err); } /******** Band setting ******/ if (nBand) { err = HPI_Tuner_SetBand(hSubSys, hTuner, nBand); HandleErrorComment("SetBand", err); } /******** Frequency setting ******/ if (nTunerFrequency) { err = HPI_Tuner_SetFrequency(hSubSys, hTuner, nTunerFrequency); HandleErrorComment("SetFrequency", err); } asi_sleep(nanosec / 1000000); /******** Query capabilities ******/ if (query_tuner_caps) { uint32_t dwIndex; uint16_t wSetting; err = HPI_MixerGetControl(hSubSys, hMixer, HPI_SOURCENODE_TUNER, nTunerIndex, 0, 0, HPI_CONTROL_TUNER, &hTuner); if (err == 0) { printf("\nTuner %d supports\n", nTunerIndex); for (dwIndex = 0; dwIndex < 100; dwIndex++) { err = HPI_Tuner_QueryBand(hSubSys, hTuner, dwIndex, &wSetting); if (err != 0) break; if ((wSetting == 0) || (wSetting > HPI_TUNER_BAND_LAST)) { printf("Unknown band type %d\n", wSetting); continue; } printf("%i %s : ", dwIndex, band_names[wSetting]); { uint32_t dwStart, dwEnd, dwStep; err = HPI_Tuner_QueryFrequency (hSubSys, hTuner, 0, wSetting, &dwStart); err = HPI_Tuner_QueryFrequency (hSubSys, hTuner, 1, wSetting, &dwEnd); err = HPI_Tuner_QueryFrequency (hSubSys, hTuner, 2, wSetting, &dwStep); printf("from %ikHz to %ikHz step %ikHz\n", dwStart, dwEnd, dwStep); } } } } /******** Query settings ******/ if (query_tuner_settings) { uint16_t nTunerBand = 0; short int nRfLevel = 0; uint32_t nTunerFrequency = 0; uint32_t wMode = 0; uint16_t wMuxIndex = 0; uint16_t wStatus = 0; uint16_t wStatusMask = 0; err = HPI_Tuner_GetBand(hSubSys, hTuner, &nTunerBand); HandleErrorComment("HPI_Tuner_GetBand", err); err = HPI_Tuner_GetFrequency(hSubSys, hTuner, &nTunerFrequency); HandleErrorComment("HPI_Tuner_GetFrequency", err); err = HPI_Tuner_GetRFLevel(hSubSys, hTuner, &nRfLevel); HandleErrorComment("HPI_Tuner_GetRFLevel", err); err = HPI_Multiplexer_GetSource(hSubSys, hMux, 0, &wMuxIndex); HandleErrorComment("HPI_Multiplexer_GetSource", err); err = HPI_Tuner_GetStatus(hSubSys, hTuner, &wStatusMask, &wStatus); HandleErrorComment("HPI_Tuner_GetStatus", err); printf("Current Settings %s band, frequency %i. Mode %d. RF level %3.2fdBuV. Mux=%d\n", band_names[nTunerBand], nTunerFrequency, wMode, nRfLevel / 100.0, wMuxIndex); printf("Status mask %08X, value %08X\n", wStatusMask, wStatus); err = HPI_Tuner_GetMode(hSubSys, hTuner, HPI_TUNER_MODE_RSS, &wMode); if (err == HPI_ERROR_INVALID_CONTROL_ATTRIBUTE) { verbose_printf("Tuner does not have MODEs.\n"); wMode = 0; } else if ( err == HPI_ERROR_INVALID_CONTROL_VALUE) { verbose_printf("TUNER_MODE_RSS not supported\n"); wMode = 0; } else { HandleErrorComment("HPI_Tuner_GetMode", err); printf("TUNER_MODE_RSS %d\n", wMode); } if (err != HPI_ERROR_INVALID_CONTROL_ATTRIBUTE) { err = HPI_Tuner_GetMode(hSubSys, hTuner, HPI_TUNER_MODE_RDS, &wMode); if ( err == HPI_ERROR_INVALID_CONTROL_VALUE) { verbose_printf("TUNER_MODE_RDS not supported\n"); wMode = 0; } else { HandleErrorComment("HPI_Tuner_GetMode", err); printf("TUNER_MODE_RDS %d\n", wMode); } } } /******** RDS ******/ if (rds) { hpi_handle_t hPad = 0; unsigned int nRDSloopcount = rds_poll_loops; uint32_t dwPTY = 0, dwPI = 0; hpi_err_t ecn = 0, ec = 0, epi = 0; err = HPI_MixerGetControl(hSubSys, hMixer, HPI_SOURCENODE_TUNER, nTunerIndex, 0, 0, HPI_CONTROL_PAD, &hPad); HandleErrorComment("HPI_MixerGetControl (HPI_CONTROL_PAD)", err); if (err) nRDSloopcount = 1; while (--nRDSloopcount) { char szPAD[HPI_PAD_COMMENT_LEN]; printf("\nLoop - %d\n", nRDSloopcount); if (verbose) { unsigned char aRDS[12]; // RDS data group of (4 blocks each of 16 bits) plus 4 chars of error information err = HPI_Tuner_GetRDS(hSubSys, hTuner, (char *)aRDS); if (!err) { int i; printf("RDS block data "); for (i = 0; i < 12; i++) printf("%u ", aRDS[i]); printf("\n"); /* Output PI from RDS data. */ printf("PI from ^---^ = 0x%X\n", aRDS[1] << 8 | aRDS[0]); } else HandleErrorCommentContinue ("HPI_Tuner_GetRDS", err); } /* Note, depending on whether the tuner supports HDRadio PAD information or FM RDS information, different attributes may be valid. */ if (!ecn) { ecn = HPI_PAD_GetChannelName(hSubSys, hPad, szPAD, sizeof(szPAD)); HandleErrorCommentContinue ("HPI_PAD_GetChannelName", ecn); if (!ecn) printf("ChannelName : %s\n", szPAD); } err = HPI_PAD_GetArtist(hSubSys, hPad, szPAD, sizeof(szPAD)); HandleErrorComment("HPI_PAD_GetArtist", err); if (!err) printf("Artist/RT : %s\n", szPAD); err = HPI_PAD_GetTitle(hSubSys, hPad, szPAD, sizeof(szPAD)); HandleErrorComment("HPI_PAD_GetTitle", err); if (!err) printf("Title/PS : %s\n", szPAD); if (!ec) { ec = HPI_PAD_GetComment(hSubSys, hPad, szPAD, sizeof(szPAD)); HandleErrorCommentContinue ("HPI_PAD_GetComment", ec); if (!ec) printf("Comment/PS : %s\n", szPAD); } err = HPI_PAD_GetProgramType(hSubSys, hPad, &dwPTY); HandleErrorComment("HPI_PAD_GetProgramType", err); if (!err) { err = HPI_PAD_GetProgramTypeString(hSubSys, hPad, HPI_RDS_DATATYPE_RBDS, dwPTY, szPAD, sizeof(szPAD)); if (!err) printf("PTY : %d, %s\n", dwPTY, szPAD); } if (!epi) { epi = HPI_PAD_GetRdsPI(hSubSys, hPad, &dwPI); HandleErrorCommentContinue("HPI_PAD_GetRdsPI", epi); if (!epi) printf("PI : 0x%X\n", dwPI); } asi_sleep(rds_poll_ms); } } /* if (rds) */ close: err = HPI_MixerClose(hSubSys, hMixer); verbose_printf("\nHPI_MixerClose\n"); HandleError(err); err = HPI_AdapterClose(hSubSys, wAdapterIndex); verbose_printf("HPI_AdapterClose\n"); HandleError(err); err = HPI_AdapterClose(hSubSys, wAdapterIndex); HPI_SubSysFree(hSubSys); return 0; } /****************************** HandleError **********************/ static void HandleErrorCommentContinue( char *comment, hpi_err_t err ) { char szError[256]; if (err) { printf("\t\t%s\n", comment); HPI_GetErrorText(err, szError); printf("\t\tERROR %s\n", szError); } } static void HandleError( hpi_err_t err ) { char szError[256]; char nK = 0; if (err) { HPI_GetErrorText(err, szError); printf("ERROR %d %s\n", err, szError); printf("\tpress Enter to continue, (q,Enter) to exit...\n"); nK = getch(); if (nK == 'q') exit(0); } } static void HandleErrorComment( char *comment, hpi_err_t err ) { if (err) printf("%s ", comment); HandleError(err); } static int getch( void ) { return getchar(); } /****************************** asi_sleep **********************/ static void asi_sleep( unsigned int milliseconds ) { #if defined(HPI_OS_LINUX) || defined(__APPLE__) struct timespec req = { milliseconds / 1000, (milliseconds % 1000) * 1000000 }; nanosleep(&req, 0); #else Sleep(milliseconds); #endif } /* END_OF_CODE */
1.7.3