annotate core/RTAudioCommandLine.cpp @ 45:579c86316008 newapi

Major API overhaul. Moved to a single data structure for handling render functions. Functionally, generally similar except for scheduling within PRU loop function, which now uses interrupts from the PRU rather than polling. This requires an updated kernel.
author andrewm
date Thu, 28 May 2015 14:35:55 -0400
parents 46d87f680da5
children 643cbee74eda
rev   line source
andrewm@5 1 /*
andrewm@5 2 * RTAudioCommandLine.cpp
andrewm@5 3 *
andrewm@5 4 * Created on: Nov 8, 2014
andrewm@5 5 * Author: parallels
andrewm@5 6 */
andrewm@5 7
andrewm@5 8 #include <iostream>
andrewm@5 9 #include <cstdlib>
andrewm@5 10 #include <cstring>
andrewm@5 11 #include <getopt.h>
andrewm@45 12 #include "../include/BeagleRT.h"
giuliomoro@24 13
giuliomoro@23 14 #ifndef OPT_PRU_FILE
andrewm@45 15 #define OPT_PRU_FILE 176 // this is an extended ASCII code
giuliomoro@23 16 #endif
andrewm@5 17
andrewm@5 18 // Default command-line options for RTAudio
andrewm@5 19 struct option gDefaultLongOptions[] =
andrewm@5 20 {
andrewm@5 21 {"period", 1, NULL, 'p'},
andrewm@5 22 {"verbose", 0, NULL, 'v'},
giuliomoro@19 23 {"use-analog", 1, NULL, 'm'},
giuliomoro@23 24 {"use-digital-gpio", 1, NULL, 'g'},
giuliomoro@19 25 {"analog-channels", 1, NULL, 'C'},
giuliomoro@24 26 {"digital-channels", 1, NULL, 'G'},
andrewm@5 27 {"mute-speaker", 1, NULL, 'M'},
andrewm@5 28 {"dac-level", 1, NULL, 'D'},
andrewm@5 29 {"adc-level", 1, NULL, 'A'},
andrewm@5 30 {"hp-level", 1, NULL, 'H'},
giuliomoro@24 31 {"receive-port", 1, NULL, 'r'},
giuliomoro@24 32 {"transmit-port", 1, NULL, 't'},
andrewm@45 33 {"server-name", 1, NULL, 's'},
andrewm@45 34 {"pru-file", 1, NULL, OPT_PRU_FILE},
andrewm@5 35 {NULL, 0, NULL, 0}
andrewm@5 36 };
giuliomoro@24 37
giuliomoro@24 38 const char gDefaultShortOptions[] = "p:vm:M:C:D:A:H:g:G:r:t:s:";
andrewm@5 39
andrewm@45 40 // This function sets the default settings for the BeagleRTInitSettings structure
andrewm@45 41 void BeagleRT_defaultSettings(BeagleRTInitSettings *settings)
andrewm@5 42 {
andrewm@5 43 // Set default values for settings
andrewm@5 44 settings->periodSize = 8;
andrewm@45 45 settings->useAnalog = 1;
andrewm@45 46 settings->useDigital = 1;
andrewm@45 47 settings->numAnalogChannels = 8;
andrewm@45 48 settings->numDigitalChannels = 16;
andrewm@45 49
andrewm@5 50 settings->beginMuted = 0;
andrewm@5 51 settings->dacLevel = DEFAULT_DAC_LEVEL;
andrewm@5 52 settings->adcLevel = DEFAULT_ADC_LEVEL;
andrewm@5 53 settings->headphoneLevel = DEFAULT_HP_LEVEL;
andrewm@45 54
andrewm@5 55 settings->verbose = 0;
andrewm@45 56 settings->pruFilename[0] = '\0';
andrewm@45 57
andrewm@45 58 // These two deliberately have no command-line flags by default.
andrewm@45 59 // A given program might prefer one mode or another, but it's unlikely
andrewm@45 60 // the user would want to switch at runtime
andrewm@45 61 settings->interleave = 1;
andrewm@45 62 settings->analogOutputsPersist = 1;
andrewm@45 63
andrewm@5 64 settings->codecI2CAddress = CODEC_I2C_ADDRESS;
andrewm@45 65 settings->receivePort = 9998;
andrewm@45 66 settings->transmitPort = 9999;
giuliomoro@24 67 strcpy(settings->serverName, "127.0.0.1");
andrewm@5 68 settings->ampMutePin = kAmplifierMutePin;
andrewm@5 69 }
andrewm@5 70
andrewm@5 71 // This function drops in place of getopt() in the main() function
andrewm@5 72 // and handles the initialisation of the RTAudio settings using
andrewm@5 73 // standard command-line arguments. System default arguments will
andrewm@5 74 // be stored in settings, otherwise arguments will be returned
andrewm@5 75 // as getopt() normally does.
andrewm@5 76
andrewm@45 77 int BeagleRT_getopt_long(int argc, char *argv[], const char *customShortOptions, const struct option *customLongOptions, BeagleRTInitSettings *settings)
andrewm@5 78 {
andrewm@5 79 static int firstRun = 1;
andrewm@5 80 static char totalShortOptions[256];
andrewm@5 81 static struct option totalLongOptions[256];
andrewm@5 82
andrewm@5 83 int c;
andrewm@5 84
andrewm@5 85 // Prep total option string the first time this is
andrewm@5 86 // run. As a getopt() substitute, it will be called repeatedly working its
andrewm@5 87 // way through argc and argv.
andrewm@5 88 if(firstRun) {
andrewm@5 89 firstRun = 0;
andrewm@5 90
andrewm@5 91 // Copy short options into one string
andrewm@5 92 strcpy(totalShortOptions, gDefaultShortOptions);
andrewm@5 93 strncat(totalShortOptions, customShortOptions, 256 - strlen(gDefaultShortOptions) - 1);
andrewm@5 94
andrewm@5 95 // Copy long options into one array
andrewm@5 96 int n = 0;
andrewm@5 97 while(1) {
andrewm@5 98 if(gDefaultLongOptions[n].name == NULL)
andrewm@5 99 break;
andrewm@5 100 totalLongOptions[n].name = gDefaultLongOptions[n].name;
andrewm@5 101 totalLongOptions[n].has_arg = gDefaultLongOptions[n].has_arg;
andrewm@5 102 totalLongOptions[n].flag = gDefaultLongOptions[n].flag;
andrewm@5 103 totalLongOptions[n].val = gDefaultLongOptions[n].val;
andrewm@5 104 n++;
andrewm@5 105 }
andrewm@5 106
andrewm@5 107 // Copy custom options into the array, if present
andrewm@5 108 if(customLongOptions == 0) {
andrewm@5 109 // Terminate the array
andrewm@5 110 totalLongOptions[n].name = NULL;
andrewm@5 111 totalLongOptions[n].has_arg = 0;
andrewm@5 112 totalLongOptions[n].flag = NULL;
andrewm@5 113 totalLongOptions[n].val = 0;
andrewm@5 114 }
andrewm@5 115 else {
andrewm@5 116 int customIndex = 0;
andrewm@5 117 while(n < 256) {
andrewm@5 118 if(customLongOptions[customIndex].name == NULL)
andrewm@5 119 break;
andrewm@5 120 totalLongOptions[n].name = customLongOptions[customIndex].name;
andrewm@5 121 totalLongOptions[n].has_arg = customLongOptions[customIndex].has_arg;
andrewm@5 122 totalLongOptions[n].flag = customLongOptions[customIndex].flag;
andrewm@5 123 totalLongOptions[n].val = customLongOptions[customIndex].val;
andrewm@5 124 n++;
andrewm@5 125 customIndex++;
andrewm@5 126 }
andrewm@5 127
andrewm@5 128 // Terminate the array
andrewm@5 129 totalLongOptions[n].name = NULL;
andrewm@5 130 totalLongOptions[n].has_arg = 0;
andrewm@5 131 totalLongOptions[n].flag = NULL;
andrewm@5 132 totalLongOptions[n].val = 0;
andrewm@5 133 }
andrewm@5 134 }
andrewm@5 135
andrewm@5 136 while(1) {
andrewm@5 137 if ((c = getopt_long(argc, argv, totalShortOptions, totalLongOptions, NULL)) < 0)
andrewm@5 138 return c;
andrewm@5 139
andrewm@5 140 switch (c) {
andrewm@5 141 case 'p':
andrewm@5 142 settings->periodSize = atoi(optarg);
andrewm@5 143 if(settings->periodSize < 1)
andrewm@5 144 settings->periodSize = 1;
andrewm@5 145 break;
andrewm@5 146 case 'v':
andrewm@5 147 settings->verbose = 1;
andrewm@5 148 break;
andrewm@5 149 case 'm':
giuliomoro@19 150 settings->useAnalog = atoi(optarg);
andrewm@5 151 break;
giuliomoro@16 152 case 'g':
giuliomoro@19 153 settings->useDigital = atoi(optarg);
giuliomoro@19 154 settings->numDigitalChannels = 0;
giuliomoro@16 155 break;
andrewm@12 156 case 'C':
giuliomoro@19 157 settings->numAnalogChannels = atoi(optarg);
giuliomoro@19 158 if(settings->numAnalogChannels >= 8)
giuliomoro@19 159 settings->numAnalogChannels = 8;
giuliomoro@19 160 else if(settings->numAnalogChannels >= 4)
giuliomoro@19 161 settings->numAnalogChannels = 4;
andrewm@12 162 else
giuliomoro@19 163 settings->numAnalogChannels = 2;
andrewm@12 164 break;
giuliomoro@16 165 case 'G':
giuliomoro@19 166 settings->numDigitalChannels = atoi(optarg);
giuliomoro@19 167 if(settings->numDigitalChannels >= 16)
giuliomoro@19 168 settings->numDigitalChannels = 16;
giuliomoro@19 169 else if (settings->numDigitalChannels < 1){
giuliomoro@19 170 settings->numDigitalChannels = 0;
giuliomoro@19 171 settings->useDigital = 0; //TODO: this actually works only if -G 0 is specified after -g 1.
giuliomoro@19 172 //No worries, though: disabling numDigital will only prevent the pins from being exported.
giuliomoro@16 173 }
giuliomoro@16 174 break;
andrewm@5 175 case 'M':
andrewm@5 176 settings->beginMuted = atoi(optarg);
andrewm@5 177 break;
andrewm@5 178 case 'D':
andrewm@5 179 settings->dacLevel = atof(optarg);
andrewm@5 180 break;
andrewm@5 181 case 'A':
andrewm@5 182 settings->adcLevel = atof(optarg);
andrewm@5 183 break;
andrewm@5 184 case 'H':
andrewm@5 185 settings->headphoneLevel = atof(optarg);
andrewm@5 186 break;
giuliomoro@24 187 case 'r':
giuliomoro@24 188 settings->receivePort = atoi(optarg);
giuliomoro@24 189 break;
giuliomoro@24 190 case 't':
giuliomoro@24 191 settings->transmitPort = atoi(optarg);
giuliomoro@24 192 break;
giuliomoro@24 193 case 's':
giuliomoro@24 194 if(strlen(optarg)<MAX_SERVERNAME_LENGTH)
giuliomoro@24 195 strcpy(settings->serverName, optarg);
giuliomoro@24 196 else
giuliomoro@24 197 std::cerr << "Warning: server name is too long (>" << MAX_SERVERNAME_LENGTH << " characters)."
giuliomoro@24 198 " Using default severName Instead ( " << settings->serverName << " ).\n";
giuliomoro@24 199 break;
giuliomoro@29 200 case OPT_PRU_FILE:
andrewm@45 201 if(strlen(optarg) < MAX_PRU_FILENAME_LENGTH)
giuliomoro@16 202 strcpy(settings->pruFilename, optarg);
giuliomoro@16 203 else
giuliomoro@16 204 std::cerr << "Warning: filename for the PRU code is too long (>" << MAX_PRU_FILENAME_LENGTH << " characters). Using embedded PRU code instead\n";
giuliomoro@16 205 break;
andrewm@5 206 case '?':
andrewm@5 207 default:
andrewm@5 208 return c;
andrewm@5 209 }
andrewm@5 210 }
andrewm@5 211 }
andrewm@5 212
andrewm@5 213 // This function prints standard usage information for default arguments
andrewm@5 214 // Call from within your own usage function
andrewm@5 215 void BeagleRT_usage()
andrewm@5 216 {
giuliomoro@19 217 std::cerr << " --period [-p] period: Set the hardware period (buffer) size in analog samples\n";
giuliomoro@16 218 std::cerr << " --dac-level [-D] dBs: Set the DAC output level (0dB max; -63.5dB min)\n";
giuliomoro@16 219 std::cerr << " --adc-level [-A] dBs: Set the ADC input level (0dB max; -12dB min)\n";
giuliomoro@16 220 std::cerr << " --hp-level [-H] dBs: Set the headphone output level (0dB max; -63.5dB min)\n";
giuliomoro@16 221 std::cerr << " --mute-speaker [-M] val: Set whether to mute the speaker initially (default: no)\n";
giuliomoro@19 222 std::cerr << " --use-analog [-m] val: Set whether to use ADC/DAC analog (default: yes)\n";
giuliomoro@24 223 std::cerr << " --use-digital [-g] val: Set whether to use digital GPIO channels (default: yes)\n";
giuliomoro@19 224 std::cerr << " --analog-channels [-C] val: Set the number of ADC/DAC channels (default: 8)\n";
giuliomoro@31 225 std::cerr << " --digital-channels [-G] val: Set the number of GPIO channels (default: 16)\n";
giuliomoro@24 226 std::cerr << " --digital-channels [-G] val: Set the number of digital GPIO channels (default: 16)\n";
giuliomoro@24 227 std::cerr << " --receive-port [-r] val: Set the receive port (default: 9998)\n";
giuliomoro@24 228 std::cerr << " --transmit-port [-t] val: Set the transmit port (default: 9999)\n";
giuliomoro@24 229 std::cerr << " --server-name [-s] val: Set the destination server name (default: '127.0.0.1')\n";
giuliomoro@24 230 std::cerr << " --pru-file val: Set an optional external file to use for the PRU binary code\n";
giuliomoro@16 231 std::cerr << " --verbose [-v]: Enable verbose logging information\n";
andrewm@5 232 }
giuliomoro@16 233