Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 1 | /* |
Ayaz Ahmad | 292f940 | 2013-05-07 10:27:40 +0530 | [diff] [blame] | 2 | * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved. |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions are met: |
| 6 | * * Redistributions of source code must retain the above copyright |
| 7 | * notice, this list of conditions and the following disclaimer. |
| 8 | * * Redistributions in binary form must reproduce the above copyright |
| 9 | * notice, this list of conditions and the following disclaimer in the |
| 10 | * documentation and/or other materials provided with the distribution. |
| 11 | * * Neither the name of The Linux Foundation nor |
| 12 | * the names of its contributors may be used to endorse or promote |
| 13 | * products derived from this software without specific prior written |
| 14 | * permission. |
| 15 | * |
| 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 19 | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| 20 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 21 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 22 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| 23 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 24 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| 25 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| 26 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | */ |
| 28 | |
| 29 | package qcom.fmradio; |
| 30 | import android.util.Log; |
| 31 | |
| 32 | |
| 33 | /** |
| 34 | * This class contains all interfaces and types needed to control the FM transmitter. |
| 35 | * @hide |
| 36 | */ |
| 37 | public class FmTransmitter extends FmTransceiver |
| 38 | { |
| 39 | private final String TAG = "FmTransmitter"; |
| 40 | /** |
| 41 | * An object that contains the PS Features that SoC supports |
| 42 | * |
| 43 | * @see #getPSFeatures |
| 44 | */ |
| 45 | public class FmPSFeatures |
| 46 | { |
| 47 | public int maxPSCharacters; |
| 48 | public int maxPSStringRepeatCount; |
| 49 | }; |
| 50 | |
| 51 | |
| 52 | /** |
| 53 | * Command types for the RDS group transmission. |
| 54 | * This is used as argument to #transmitRdsGroupControl to |
| 55 | * control the RDS group transmission. |
| 56 | * |
| 57 | * @see #transmitRdsGroupControl |
| 58 | */ |
| 59 | |
| 60 | public static final int RDS_GRPS_TX_PAUSE = 0; /* Pauses the Group transmission*/ |
| 61 | |
| 62 | public static final int RDS_GRPS_TX_RESUME = 1; /* Resumes the Group transmission*/ |
| 63 | |
| 64 | public static final int RDS_GRPS_TX_STOP = 2; /* Stops and clear the Group transmission */ |
| 65 | |
| 66 | public static final int FM_TX_MAX_PS_LEN = (96+1); |
| 67 | public static final int FM_TX_MAX_RT_LEN = (64-1); /*One space to include NULL*/ |
| 68 | |
| 69 | private static final int MAX_PS_CHARS = 97; |
| 70 | private static final int MAX_PS_REP_COUNT = 15; |
| 71 | private static final int MAX_RDS_GROUP_BUF_SIZE = 62; |
| 72 | |
| 73 | private FmTransmitterCallbacksAdaptor mTxCallbacks; |
| 74 | private boolean mPSStarted = false; |
| 75 | private boolean mRTStarted = false; |
| 76 | private static final int V4L2_CID_PRIVATE_BASE = 0x8000000; |
| 77 | private static final int V4L2_CID_PRIVATE_TAVARUA_ANTENNA = V4L2_CID_PRIVATE_BASE + 18; |
| 78 | |
| 79 | /** |
| 80 | * Power settings |
| 81 | * |
| 82 | * @see #setPowerMode |
| 83 | * @see #getPowerMode |
| 84 | */ |
| 85 | public static final int FM_TX_NORMAL_POWER_MODE =0; |
| 86 | public static final int FM_TX_LOW_POWER_MODE =1; |
| 87 | |
| 88 | /** |
| 89 | * Transmit Power level settings |
| 90 | * |
| 91 | * @see #setTxPowerLevel |
| 92 | */ |
| 93 | public static final int FM_TX_PWR_LEVEL_0 =0; |
| 94 | public static final int FM_TX_PWR_LEVEL_1 =1; |
| 95 | public static final int FM_TX_PWR_LEVEL_2 =2; |
| 96 | public static final int FM_TX_PWR_LEVEL_3 =3; |
| 97 | public static final int FM_TX_PWR_LEVEL_4 =4; |
| 98 | public static final int FM_TX_PWR_LEVEL_5 =5; |
| 99 | public static final int FM_TX_PWR_LEVEL_6 =6; |
| 100 | public static final int FM_TX_PWR_LEVEL_7 =7; |
| 101 | |
| 102 | |
| 103 | /** |
| 104 | * Constructor for the transmitter class that takes path to |
| 105 | * radio device and event callback adapter |
| 106 | */ |
| 107 | public FmTransmitter(String path, FmTransmitterCallbacksAdaptor callbacks) throws InstantiationException{ |
| 108 | |
| 109 | mTxEvents = new FmTxEventListner(); |
| 110 | mControl = new FmRxControls(); |
| 111 | mTxCallbacks = callbacks; |
| 112 | } |
| 113 | |
| 114 | /*============================================================== |
| 115 | FUNCTION: enable |
| 116 | ==============================================================*/ |
| 117 | /** |
| 118 | * Enables the FM device in Transmit Mode. |
| 119 | * <p> |
| 120 | * This is a synchronous method used to initialize the FM |
| 121 | * device in transmitt mode. If already initialized this function will |
| 122 | * intialize the Fm device with default settings. Only after |
| 123 | * successfully calling this function can many of the FM device |
| 124 | * interfaces be used. |
| 125 | * <p> |
| 126 | * When enabling the transmitter, the application must also |
| 127 | * provide the regional settings in which the transmitter will |
| 128 | * operate. These settings (included in argument |
| 129 | * configSettings) are typically used for setting up the FM |
| 130 | * Transmitter for operating in a particular geographical |
| 131 | * region. These settings can be changed after the FM driver |
| 132 | * is enabled through the use of the function {@link |
| 133 | * #configure}. |
| 134 | * <p> |
| 135 | * This command can only be issued by the owner of an FM |
| 136 | * transmitter. |
| 137 | * |
| 138 | * @param configSettings the settings to be applied when |
| 139 | * turning on the radio |
| 140 | * @return true if Initialization succeeded, false if |
| 141 | * Initialization failed. |
| 142 | * <p> |
| 143 | * @see #enable |
| 144 | * @see #registerTransmitClient |
| 145 | * @see #disable |
| 146 | * |
| 147 | */ |
| 148 | public boolean enable (FmConfig configSettings){ |
Ayaz Ahmad | 44d8c5b | 2013-05-13 14:55:05 +0530 | [diff] [blame] | 149 | boolean status = false; |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 150 | |
| 151 | int state = getFMState(); |
| 152 | if (state == FMState_Tx_Turned_On) { |
| 153 | Log.d(TAG, "enable: FM Tx already turned On and running"); |
| 154 | return status; |
Ayaz Ahmad | 44d8c5b | 2013-05-13 14:55:05 +0530 | [diff] [blame] | 155 | }else if (state == subPwrLevel_FMTurning_Off) { |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 156 | Log.v(TAG, "FM is in the process of turning off.Pls wait for sometime."); |
| 157 | return status; |
Ayaz Ahmad | 44d8c5b | 2013-05-13 14:55:05 +0530 | [diff] [blame] | 158 | }else if((state == subPwrLevel_FMTx_Starting) |
| 159 | ||(state == subPwrLevel_FMRx_Starting)) { |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 160 | Log.v(TAG, "FM is in the process of turning On.Pls wait for sometime."); |
| 161 | return status; |
Ayaz Ahmad | 44d8c5b | 2013-05-13 14:55:05 +0530 | [diff] [blame] | 162 | }else if((state == FMState_Srch_InProg) |
| 163 | ||(state == FMState_Rx_Turned_On)) { |
| 164 | Log.v(TAG, "FM Rx is turned on"); |
| 165 | return status; |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 166 | } |
| 167 | setFMPowerState(subPwrLevel_FMTx_Starting); |
| 168 | Log.v(TAG, "enable: CURRENT-STATE : FMOff ---> NEW-STATE : FMTxStarting"); |
| 169 | status = super.enable(configSettings, FmTransceiver.FM_TX); |
| 170 | if(status == true) { |
| 171 | registerTransmitClient(mTxCallbacks); |
| 172 | mRdsData = new FmRxRdsData(sFd); |
| 173 | } else { |
| 174 | status = false; |
| 175 | Log.e(TAG, "enable: failed to turn On FM TX"); |
| 176 | Log.e(TAG, "enable: CURRENT-STATE : FMTxStarting ---> NEW-STATE : FMOff"); |
| 177 | setFMPowerState(FMState_Turned_Off); |
| 178 | } |
| 179 | return status; |
| 180 | } |
| 181 | /*============================================================== |
| 182 | FUNCTION: setRdsOn |
| 183 | ==============================================================*/ |
| 184 | /** |
| 185 | * |
| 186 | * This function enables RDSCTRL register for SoC. |
| 187 | * |
| 188 | * <p> |
| 189 | * This API enables the ability of the FM driver |
| 190 | * to send Program Service, RadioText information. |
| 191 | * |
| 192 | * |
| 193 | * @return true if the command was placed successfully, false |
| 194 | * if command failed. |
| 195 | * |
| 196 | */ |
| 197 | public boolean setRdsOn (){ |
| 198 | |
| 199 | if (mRdsData == null) |
| 200 | return false; |
| 201 | // Enable RDS |
| 202 | int re = mRdsData.rdsOn(true); |
| 203 | |
| 204 | if (re ==0) |
| 205 | return true; |
| 206 | |
| 207 | return false; |
| 208 | } |
| 209 | |
| 210 | /*============================================================== |
| 211 | FUNCTION: disable |
| 212 | ==============================================================*/ |
| 213 | /** |
| 214 | * Disables the FM Transmitter Device. |
| 215 | * <p> |
| 216 | * This is a synchronous command used to disable the FM |
| 217 | * device. This function is expected to be used when the |
| 218 | * application no longer requires use of the FM device. Once |
| 219 | * called, most functionality offered by the FM device will be |
| 220 | * disabled until the application re-enables the device again |
| 221 | * via {@link #enable}. |
| 222 | * |
| 223 | * <p> |
| 224 | * @return true if disabling succeeded, false if disabling |
| 225 | * failed. |
| 226 | * |
| 227 | * @see #enable |
| 228 | * @see #registerTransmitClient |
| 229 | */ |
| 230 | public boolean disable(){ |
| 231 | boolean status = false; |
| 232 | int state; |
| 233 | |
| 234 | state = getFMState(); |
| 235 | switch(state) { |
| 236 | case FMState_Turned_Off: |
| 237 | Log.d(TAG, "FM already tuned Off."); |
| 238 | return true; |
| 239 | case subPwrLevel_FMTx_Starting: |
| 240 | /* |
| 241 | * If, FM is in the process of turning On, then wait for |
| 242 | * the turn on operation to complete before turning off. |
| 243 | */ |
| 244 | Log.d(TAG, "disable: FM not yet turned On..."); |
| 245 | try { |
| 246 | Thread.sleep(100); |
| 247 | } catch (InterruptedException e) { |
| 248 | e.printStackTrace(); |
| 249 | } |
| 250 | /* Check for the state of FM device */ |
| 251 | state = getFMState(); |
| 252 | if(state == subPwrLevel_FMTx_Starting) { |
| 253 | Log.e(TAG, "disable: FM in bad state"); |
| 254 | return status; |
| 255 | } |
| 256 | break; |
| 257 | case subPwrLevel_FMTurning_Off: |
| 258 | /* |
| 259 | * If, FM is in the process of turning Off, then wait for |
| 260 | * the turn off operation to complete. |
| 261 | */ |
| 262 | Log.v(TAG, "disable: FM is getting turned Off."); |
| 263 | return status; |
| 264 | } |
| 265 | setFMPowerState(subPwrLevel_FMTurning_Off); |
| 266 | Log.v(TAG, "disable: CURRENT-STATE : FMTxOn ---> NEW-STATE : FMTurningOff"); |
| 267 | //Stop all the RDS transmissions if there any |
| 268 | if(mPSStarted) { |
| 269 | if(!stopPSInfo()) { |
| 270 | Log.d(TAG, "FmTrasmitter:stopPSInfo failed\n"); |
| 271 | } |
| 272 | } |
| 273 | if(mRTStarted) { |
| 274 | if(!stopRTInfo()) { |
| 275 | Log.d(TAG, "FmTrasmitter:stopRTInfo failed\n"); |
| 276 | } |
| 277 | } |
| 278 | if(!transmitRdsGroupControl(RDS_GRPS_TX_STOP) ) { |
| 279 | Log.d(TAG, "FmTrasmitter:transmitRdsGroupControl failed\n"); |
| 280 | } |
| 281 | super.disable(); |
| 282 | return true; |
| 283 | } |
| 284 | |
| 285 | /*============================================================== |
| 286 | FUNCTION: reset |
| 287 | ==============================================================*/ |
| 288 | /** |
| 289 | * Reset the FM Device. |
| 290 | * <p> |
| 291 | * This is a synchronous command used to reset the state of FM |
| 292 | * device in case of unrecoverable error. This function is |
| 293 | * expected to be used when the client receives unexpected |
| 294 | * notification of radio disabled. Once called, most |
| 295 | * functionality offered by the FM device will be disabled |
| 296 | * until the client re-enables the device again via |
| 297 | * {@link #enable}. |
| 298 | * <p> |
| 299 | * @return true if reset succeeded, false if reset failed. |
| 300 | * @see #enable |
| 301 | * @see #disable |
| 302 | * @see #registerTransmitClient |
| 303 | */ |
| 304 | public boolean reset(){ |
| 305 | boolean status = false; |
Ayaz Ahmad | 292f940 | 2013-05-07 10:27:40 +0530 | [diff] [blame] | 306 | int state = getFMState(); |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 307 | |
Ayaz Ahmad | 292f940 | 2013-05-07 10:27:40 +0530 | [diff] [blame] | 308 | if(state == FMState_Turned_Off) { |
| 309 | Log.d(TAG, "FM already turned Off."); |
| 310 | return false; |
| 311 | } |
| 312 | setFMPowerState(FMState_Turned_Off); |
| 313 | Log.v(TAG, "reset: NEW-STATE : FMState_Turned_Off"); |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 314 | status = unregisterTransmitClient(); |
Ayaz Ahmad | 292f940 | 2013-05-07 10:27:40 +0530 | [diff] [blame] | 315 | release("/dev/radio0"); |
Venkateshwarlu Domakonda | aa25363 | 2013-03-25 16:53:03 +0530 | [diff] [blame] | 316 | return status; |
| 317 | } |
| 318 | |
| 319 | /*============================================================== |
| 320 | FUNCTION: setStation |
| 321 | ==============================================================*/ |
| 322 | /** |
| 323 | * Tunes the FM device to the specified FM frequency. |
| 324 | * <p> |
| 325 | * This method tunes the FM device to a station specified by the |
| 326 | * provided frequency. Only valid frequencies within the band |
| 327 | * set by enable or configure can be tuned by this function. |
| 328 | * Attempting to tune to frequencies outside of the set band |
| 329 | * will result in an error. |
| 330 | * <p> |
| 331 | * Once tuning to the specified frequency is completed, the |
| 332 | * event callback FmTransmitterCallbacks::onTuneStatusChange will be called. |
| 333 | * |
| 334 | * @param frequencyKHz Frequency (in kHz) to be tuned |
| 335 | * (Example: 96500 = 96.5Mhz) |
| 336 | * @return true if setStation call was placed successfully, |
| 337 | * false if setStation failed. |
| 338 | */ |
| 339 | public boolean setStation (int frequencyKHz) { |
| 340 | |
| 341 | //Stop If there is any ongoing RDS transmissions |
| 342 | boolean status = false; |
| 343 | if( mPSStarted ){ |
| 344 | Log.d(TAG,"FmTransmitter:setStation mPSStarted"); |
| 345 | if( !stopPSInfo() ) return status; |
| 346 | } |
| 347 | if( mRTStarted ) { |
| 348 | Log.d(TAG,"FmTransmitter:setStation mRTStarted"); |
| 349 | if(!stopRTInfo()) return status; |
| 350 | } |
| 351 | if(!transmitRdsGroupControl(RDS_GRPS_TX_STOP) )return status; |
| 352 | |
| 353 | Log.d(TAG, "FmTrasmitter:SetStation\n"); |
| 354 | status = super.setStation(frequencyKHz); |
| 355 | |
| 356 | return status; |
| 357 | } |
| 358 | /*============================================================== |
| 359 | FUNCTION: setPowerMode |
| 360 | ==============================================================*/ |
| 361 | /** |
| 362 | * Puts the driver into or out of low power mode. |
| 363 | * |
| 364 | * <p> |
| 365 | * This is an synchronous command which can put the FM |
| 366 | * device and driver into and out of low power mode. Low power mode |
| 367 | * should be used when the receiver is tuned to a station and only |
| 368 | * the FM audio is required. The typical scenario for low power mode |
| 369 | * is when the FM application is no longer visible. |
| 370 | * |
| 371 | * <p> |
| 372 | * While in low power mode, all normal FM and RDS indications from |
| 373 | * the FM driver will be suppressed. By disabling these indications, |
| 374 | * low power mode can result in fewer interruptions and this may lead |
| 375 | * to a power savings. |
| 376 | * |
| 377 | * <p> |
| 378 | * @param powerMode the new driver operating mode. |
| 379 | * |
| 380 | * @return true if setPowerMode succeeded, false if |
| 381 | * setPowerMode failed. |
| 382 | */ |
| 383 | public boolean setPowerMode(int powerMode){ |
| 384 | |
| 385 | int re; |
| 386 | |
| 387 | if (powerMode == FM_TX_LOW_POWER_MODE) { |
| 388 | re = mControl.setLowPwrMode (sFd, true); |
| 389 | } |
| 390 | else { |
| 391 | re = mControl.setLowPwrMode (sFd, false); |
| 392 | } |
| 393 | |
| 394 | if (re == 0) |
| 395 | return true; |
| 396 | return false; |
| 397 | } |
| 398 | |
| 399 | |
| 400 | /*============================================================== |
| 401 | FUNCTION: getPSFeatures |
| 402 | ==============================================================*/ |
| 403 | /** |
| 404 | * This function returns the features supported by the FM |
| 405 | * driver when using {@link #setPSInfo}. |
| 406 | * <p> |
| 407 | * This function is used to get the features the FM driver |
| 408 | * supports when transmitting Program Service information. |
| 409 | * Included in the returned features is the number of Program |
| 410 | * Service (PS) characters which can be transmitted using |
| 411 | * {@link #setPSInfo}. If the driver supports continuous |
| 412 | * transmission of Program Service Information, this function |
| 413 | * will return a value greater than 0 for |
| 414 | * FmPSFeatures.maxPSCharacters. Although the RDS/RBDS |
| 415 | * standard defines each Program Service (PS) string as eight |
| 416 | * characters in length, the FM driver may have the ability to |
| 417 | * accept a string that is greater than eight character. This |
| 418 | * extended string will thenbe broken up into multiple strings |
| 419 | * of length eight and transmitted continuously. |
| 420 | * <p> |
| 421 | * When transmitting more than one string, the application may |
| 422 | * want to control the timing of how long each string is |
| 423 | * transmitted. Included in the features returned from this |
| 424 | * function is the maximum Program Service string repeat count |
| 425 | * (FmPSFeatures.maxPSStringRepeatCount). When using the |
| 426 | * function {@link #setPSInfo}, the application can specify how |
| 427 | * many times each string is repeated before the next string is |
| 428 | * transmitted. |
| 429 | * |
| 430 | * @return the Program service maximum characters and repeat |
| 431 | * count |
| 432 | * |
| 433 | * @see #setPSInfo |
| 434 | * |
| 435 | */ |
| 436 | public FmPSFeatures getPSFeatures(){ |
| 437 | FmPSFeatures psFeatures = new FmPSFeatures(); |
| 438 | |
| 439 | psFeatures.maxPSCharacters = MAX_PS_CHARS; |
| 440 | psFeatures.maxPSStringRepeatCount = MAX_PS_REP_COUNT; |
| 441 | return psFeatures; |
| 442 | } |
| 443 | |
| 444 | /*============================================================== |
| 445 | FUNCTION: startPSInfo |
| 446 | ==============================================================*/ |
| 447 | /** |
| 448 | * Continuously transmit RDS/RBDS Program Service information |
| 449 | * over an already tuned station. |
| 450 | * <p> |
| 451 | * This is a synchronous function used to continuously transmit Program |
| 452 | * Service information over an already tuned station. While |
| 453 | * Program Service information can be transmitted using {@link |
| 454 | * #transmitRdsGroups} and 0A/0B groups, this function makes |
| 455 | * the same output possible with limited input needed from the |
| 456 | * application. |
| 457 | * <p> |
| 458 | * Included in the Program Service information is an RDS/RBDS |
| 459 | * program type (PTY), and one or more Program Service |
| 460 | * strings. The program type (PTY) is used to describe the |
| 461 | * content being transmitted and follows the RDS/RBDS program |
| 462 | * types described in the RDS/RBDS specifications. |
| 463 | * <p> |
| 464 | * Program Service information also includes an eight |
| 465 | * character string. This string can be used to display any |
| 466 | * information, but is typically used to display information |
| 467 | * about the audio being transmitted. Although the RDS/RBDS |
| 468 | * standard defines a Program Service (PS) string as eight |
| 469 | * characters in length, the FM driver may have the ability to |
| 470 | * accept a string that is greater than eight characters. This |
| 471 | * extended string will then be broken up into multiple eight |
| 472 | * character strings which will be transmitted continuously. |
| 473 | * All strings passed to this function must be terminated by a |
| 474 | * null character (0x00). |
| 475 | * <p> |
| 476 | * When transmitting more than one string, the application may |
| 477 | * want to control the timing of how long each string is |
| 478 | * transmitted. To control this timing and to ensure that the FM |
| 479 | * receiver receives each string, the application can specify |
| 480 | * how many times each string is repeated before the next string |
| 481 | * is transmitted. This command can only be issued by the owner |
| 482 | * of an FM transmitter. |
| 483 | * <p> |
| 484 | * Maximux Programme service string lenght that can be sent is |
| 485 | * FM_TX_MAX_PS_LEN. If the application sends PS string longer than |
| 486 | * this threshold, string will be truncated to FM_TX_MAX_PS_LEN. |
| 487 | * |
| 488 | * @param psStr the program service strings to transmit |
| 489 | * @param pty the program type to use in the program Service |
| 490 | * information. |
| 491 | * @param pi the program type to use in the program Service |
| 492 | * information. |
| 493 | * @param repeatCount the number of times each 8 char string is |
| 494 | * repeated before next string |
| 495 | * |
| 496 | * @return true if PS information was successfully sent to the |
| 497 | * driver, false if PS information could not be sent |
| 498 | * to the driver. |
| 499 | * |
| 500 | * @see #getPSFeatures |
| 501 | * @see #stopPSInfo |
| 502 | */ |
| 503 | public boolean startPSInfo(String psStr, int pty, int pi, int repeatCount){ |
| 504 | |
| 505 | //Set the PTY |
| 506 | if((pty < 0) || (pty > 31 )) { |
| 507 | Log.d(TAG,"pTy is expected from 0 to 31"); |
| 508 | return false; |
| 509 | } |
| 510 | |
| 511 | int err = FmReceiverJNI.setPTYNative( sFd, pty ); |
| 512 | if( err < 0 ){ |
| 513 | Log.d(TAG,"setPTYNative is failure"); |
| 514 | return false; |
| 515 | } |
| 516 | |
| 517 | if((pi < 0) || (pi > 65535)) { |
| 518 | Log.d(TAG,"pi is expected from 0 to 65535"); |
| 519 | return false; |
| 520 | } |
| 521 | |
| 522 | //Set the PI |
| 523 | err = FmReceiverJNI.setPINative( sFd, pi ); |
| 524 | if( err < 0 ){ |
| 525 | Log.d(TAG,"setPINative is failure"); |
| 526 | return false; |
| 527 | } |
| 528 | |
| 529 | if((repeatCount < 0) || (repeatCount > 15)) { |
| 530 | Log.d(TAG,"repeat count is expected from 0 to 15"); |
| 531 | return false; |
| 532 | } |
| 533 | |
| 534 | err = FmReceiverJNI.setPSRepeatCountNative( sFd, repeatCount ); |
| 535 | if( err < 0 ){ |
| 536 | Log.d(TAG,"setPSRepeatCountNative is failure"); |
| 537 | return false; |
| 538 | } |
| 539 | |
| 540 | if( psStr.length() > FM_TX_MAX_PS_LEN ){ |
| 541 | /*truncate the PS string to |
| 542 | MAX possible length*/ |
| 543 | psStr = psStr.substring( 0, FM_TX_MAX_PS_LEN ); |
| 544 | |
| 545 | } |
| 546 | |
| 547 | err = FmReceiverJNI.startPSNative( sFd, psStr , psStr.length() ); |
| 548 | Log.d(TAG,"return for startPS is "+err); |
| 549 | |
| 550 | if( err < 0 ){ |
| 551 | Log.d(TAG, "FmReceiverJNI.startPSNative returned false\n"); |
| 552 | return false; |
| 553 | |
| 554 | } else { |
| 555 | Log.d(TAG,"startPSNative is successful"); |
| 556 | mPSStarted = true; |
| 557 | return true; |
| 558 | } |
| 559 | } |
| 560 | |
| 561 | /*============================================================== |
| 562 | FUNCTION: stopPSInfo |
| 563 | ==============================================================*/ |
| 564 | /** |
| 565 | * Stops an active Program Service transmission. |
| 566 | * |
| 567 | * <p> |
| 568 | * This is a synchrnous function used to stop an active Program Service transmission |
| 569 | * started by {@link #startPSInfo}. |
| 570 | * |
| 571 | * @return true if Stop PS information was successfully sent to |
| 572 | * the driver, false if Stop PS information could not |
| 573 | * be sent to the driver. |
| 574 | * |
| 575 | * @see #getPSFeatures |
| 576 | * @see #startPSInfo |
| 577 | * |
| 578 | */ |
| 579 | public boolean stopPSInfo(){ |
| 580 | int err =0; |
| 581 | if( (err =FmReceiverJNI.stopPSNative( sFd )) < 0 ){ |
| 582 | Log.d(TAG,"return for startPS is "+err); |
| 583 | return false; |
| 584 | } else{ |
| 585 | Log.d(TAG,"stopPSNative is successful"); |
| 586 | mPSStarted = false; |
| 587 | return true; |
| 588 | } |
| 589 | } |
| 590 | |
| 591 | |
| 592 | /*============================================================== |
| 593 | FUNCTION: startRTInfo |
| 594 | ==============================================================*/ |
| 595 | /** |
| 596 | * Continuously transmit RDS/RBDS RadioText information over an |
| 597 | * already tuned station. |
| 598 | * |
| 599 | * <p> |
| 600 | * This is a synchronous function used to continuously transmit RadioText |
| 601 | * information over an already tuned station. While RadioText |
| 602 | * information can be transmitted using |
| 603 | * {@link #transmitRdsGroups} and 2A/2B groups, this function |
| 604 | * makes the same output possible with limited input needed from |
| 605 | * the application. |
| 606 | * <p> |
| 607 | * Included in the RadioText information is an RDS/RBDS program type (PTY), |
| 608 | * and a single string of up to 64 characters. The program type (PTY) is used |
| 609 | * to describe the content being transmitted and follows the RDS/RBDS program |
| 610 | * types described in the RDS/RBDS specifications. |
| 611 | * <p> |
| 612 | * RadioText information also includes a string that consists of up to 64 |
| 613 | * characters. This string can be used to display any information, but is |
| 614 | * typically used to display information about the audio being transmitted. |
| 615 | * This RadioText string is expected to be at 64 characters in length, or less |
| 616 | * than 64 characters and terminated by a return carriage (0x0D). All strings |
| 617 | * passed to this function must be terminated by a null character (0x00). |
| 618 | * <p> |
| 619 | * <p> |
| 620 | * Maximux Radio Text string length that can be sent is |
| 621 | * FM_TX_MAX_RT_LEN. If the application sends RT string longer than |
| 622 | * this threshold, string will be truncated to FM_TX_MAX_RT_LEN. |
| 623 | * |
| 624 | * @param rtStr the Radio Text string to transmit |
| 625 | * @param pty the program type to use in the Radio text |
| 626 | * transmissions. |
| 627 | * @param pi the program identifier to use in the Radio text |
| 628 | * transmissions. |
| 629 | * |
| 630 | * @return true if RT information String was successfully sent |
| 631 | * to the driver, false if RT information string |
| 632 | * could not be sent to the driver. |
| 633 | * |
| 634 | * @see #stopRTInfo |
| 635 | */ |
| 636 | public boolean startRTInfo(String rtStr, int pty, int pi){ |
| 637 | |
| 638 | if((pty < 0) || (pty > 31 )) { |
| 639 | Log.d(TAG,"pTy is expected from 0 to 31"); |
| 640 | return false; |
| 641 | } |
| 642 | //Set the PTY |
| 643 | int err = FmReceiverJNI.setPTYNative( sFd, pty ); |
| 644 | if( err < 0 ){ |
| 645 | Log.d(TAG,"setPTYNative is failure"); |
| 646 | return false; |
| 647 | } |
| 648 | |
| 649 | if((pi < 0) || (pi > 65535)) { |
| 650 | Log.d(TAG,"pi is expected from 0 to 65535"); |
| 651 | return false; |
| 652 | } |
| 653 | |
| 654 | err = FmReceiverJNI.setPINative( sFd, pi ); |
| 655 | if( err < 0 ){ |
| 656 | Log.d(TAG,"setPINative is failure"); |
| 657 | return false; |
| 658 | } |
| 659 | |
| 660 | |
| 661 | if( rtStr.length() > FM_TX_MAX_RT_LEN ) |
| 662 | { |
| 663 | //truncate it to max length |
| 664 | rtStr = rtStr.substring( 0, FM_TX_MAX_RT_LEN ); |
| 665 | } |
| 666 | |
| 667 | err = FmReceiverJNI.startRTNative( sFd, rtStr, rtStr.length() ); |
| 668 | |
| 669 | if( err < 0 ){ |
| 670 | Log.d(TAG, "FmReceiverJNI.startRTNative returned false\n"); |
| 671 | return false; |
| 672 | } else { |
| 673 | Log.d(TAG,"mRTStarted is true"); |
| 674 | mRTStarted = true; |
| 675 | return true; |
| 676 | } |
| 677 | } |
| 678 | |
| 679 | /*============================================================== |
| 680 | FUNCTION: stopRTInfo |
| 681 | ==============================================================*/ |
| 682 | /** |
| 683 | * Stops an active Radio Text information transmission. |
| 684 | * |
| 685 | * <p> |
| 686 | * This is a synchrnous function used to stop an active Radio Text |
| 687 | * transmission started by {@link #startRTInfo}. |
| 688 | * |
| 689 | * @return true if Stop RT information was successfully sent to |
| 690 | * the driver, false if Stop RT information could not |
| 691 | * be sent to the driver. |
| 692 | * |
| 693 | * @see #startRTInfo |
| 694 | * |
| 695 | */ |
| 696 | public boolean stopRTInfo(){ |
| 697 | |
| 698 | if( FmReceiverJNI.stopRTNative( sFd ) < 0 ){ |
| 699 | Log.d(TAG,"stopRTNative is failure"); |
| 700 | return false; |
| 701 | } else{ |
| 702 | Log.d(TAG,"mRTStarted is false"); |
| 703 | mRTStarted = false; |
| 704 | return true; |
| 705 | } |
| 706 | } |
| 707 | |
| 708 | /*============================================================== |
| 709 | FUNCTION: getRdsGroupBufSize |
| 710 | ==============================================================*/ |
| 711 | /** |
| 712 | * Get the maximum number of RDS/RBDS groups which can be passed |
| 713 | * to the FM driver. |
| 714 | * <p> |
| 715 | * This is a function used to determine the maximum RDS/RBDS |
| 716 | * buffer size for use when calling {@link #transmitRdsGroups} |
| 717 | * |
| 718 | * @return the maximum number of RDS/RBDS groups which can be |
| 719 | * passed to the FM driver at any one time. |
| 720 | * |
| 721 | */ |
| 722 | public int getRdsGroupBufSize(){ |
| 723 | |
| 724 | return MAX_RDS_GROUP_BUF_SIZE; |
| 725 | } |
| 726 | |
| 727 | |
| 728 | /*============================================================== |
| 729 | FUNCTION: transmitRdsGroups |
| 730 | ==============================================================*/ |
| 731 | /** |
| 732 | * This function will transmit RDS/RBDS groups |
| 733 | * over an already tuned station. |
| 734 | * This is an asynchronous function used to transmit RDS/RBDS |
| 735 | * groups over an already tuned station. This functionality is |
| 736 | * is currently unsupported. |
| 737 | * <p> |
| 738 | * This function accepts a buffer (rdsGroups) containing one or |
| 739 | * more RDS groups. When sending this buffer, the application |
| 740 | * must also indicate how many groups should be taken from this |
| 741 | * buffer (numGroupsToTransmit). It may be possible that the FM |
| 742 | * driver can not accept the number of group contained in the |
| 743 | * buffer and will indicate how many group were actually |
| 744 | * accepted through the return value. |
| 745 | * |
| 746 | * <p> |
| 747 | * The FM driver will indicate to the application when it is |
| 748 | * ready to accept more data via both the |
| 749 | * "onRDSGroupsAvailable()" and "onRDSGroupsComplete()" events |
| 750 | * callbacks. The "onRDSGroupsAvailable()" callback will |
| 751 | * indicate to the application that the FM driver can accept |
| 752 | * additional groups even though all groups may not have been |
| 753 | * passed to the FM transmitter. The onRDSGroupsComplete() |
| 754 | * callback will indicate when the FM driver has a complete |
| 755 | * buffer to transmit RDS data. In many cases all data passed to |
| 756 | * the FM driver will be passed to the FM hardware and only a |
| 757 | * onRDSGroupsComplete() event will be generated by the |
| 758 | * FM driver. |
| 759 | * <p> If the application attempts to send more groups than the |
| 760 | * FM driver can handle, the application must wait until it |
| 761 | * receives a onRDSGroupsAvailable or a onRDSGroupsComplete |
| 762 | * event before attempting to transmit more groups. Failure to |
| 763 | * do so may result in no group being consumed by the FM driver. |
| 764 | * <p> It is important to note that switching between continuous |
| 765 | * and non-continuous transmission of RDS groups can only happen |
| 766 | * when no RDS/RBDS group transmission is underway. If an |
| 767 | * RDS/RBDS group transmission is already underway, the |
| 768 | * application must wait for a onRDSGroupsComplete. If the application |
| 769 | * wishes to switch from continuous to non-continuous (or |
| 770 | * vice-versa) without waiting for the current transmission to |
| 771 | * complete, the application can clear all remaining groups |
| 772 | * using the {@link #transmitRdsGroupControl} command. |
| 773 | * <p> |
| 774 | * Once completed, this command will generate a |
| 775 | * onRDSGroupsComplete event to all registered applications. |
| 776 | * |
| 777 | * @param rdsGroups The RDS/RBDS groups buffer to transmit. |
| 778 | * @param numGroupsToTransmit The number of groups in the buffer |
| 779 | * to transmit. |
| 780 | * |
| 781 | * @return The number of groups the FM driver actually accepted. |
| 782 | * A value >0 indicates the command was successfully |
| 783 | * accepted and a return value of "-1" indicates error. |
| 784 | * |
| 785 | * @see #transmitRdsGroupControl |
| 786 | */ |
| 787 | |
| 788 | public int transmitRdsGroups(byte[] rdsGroups, long numGroupsToTransmit){ |
| 789 | /* |
| 790 | * This functionality is currently unsupported |
| 791 | */ |
| 792 | |
| 793 | return -1; |
| 794 | } |
| 795 | /*============================================================== |
| 796 | FUNCTION: transmitContRdsGroups |
| 797 | ==============================================================*/ |
| 798 | /** |
| 799 | * This function will continuously transmit RDS/RBDS groups over an already tuned station. |
| 800 | * <p> |
| 801 | * This is an asynchronous function used to continuously |
| 802 | * transmit RDS/RBDS groups over an already tuned station. |
| 803 | * This functionality is currently unsupported. |
| 804 | * <p> |
| 805 | * This function accepts a buffer (rdsGroups) containing one or |
| 806 | * more RDS groups. When sending this buffer, the application |
| 807 | * must also indicate how many groups should be taken from this |
| 808 | * buffer (numGroupsToTransmit). It may be possible that the FM |
| 809 | * driver can not accept the number of group contained in the |
| 810 | * buffer and will indicate how many group were actually |
| 811 | * accepted through the return value. |
| 812 | * |
| 813 | * <p> |
| 814 | * Application can send a complete RDS group buffer for the transmission. |
| 815 | * This data will be sent continuously to the driver. Only single RDS |
| 816 | * group can be continuously transmitter at a time. So, application has to |
| 817 | * send the complete RDS buffer it intends to transmit. trying to pass the |
| 818 | * single buffer in two calls will be interprted as two different RDS/RBDS |
| 819 | * groups and hence all the unset groups will be cleared. |
| 820 | * <p> |
| 821 | * As continuous RDS/RBDS group transmission is done over single buffer, |
| 822 | * Application has to wait for the "onContRDSGroupsComplete()" callback |
| 823 | * to initiate the further RDS/RBDS group transmissions. Failure to |
| 824 | * do so may result in no group being consumed by the FM driver. |
| 825 | * <p> It is important to note that switching between continuous |
| 826 | * and non-continuous transmission of RDS groups can only happen |
| 827 | * when no RDS/RBDS group transmission is underway. If an |
| 828 | * RDS/RBDS group transmission is already underway, the |
| 829 | * application must wait for a onRDSGroupsComplete or onContRDSGroupsComplete. |
| 830 | * If the application wishes to switch from continuous to non-continuous (or |
| 831 | * vice-versa) without waiting for the current transmission to |
| 832 | * complete, the application can clear all remaining groups |
| 833 | * using the {@link #transmitRdsGroupControl} command. |
| 834 | * <p> |
| 835 | * Once completed, this command will generate a |
| 836 | * onRDSContGroupsComplete event to all registered applications. |
| 837 | * |
| 838 | * @param rdsGroups The RDS/RBDS groups buffer to transmit. |
| 839 | * @param numGroupsToTransmit The number of groups in the buffer |
| 840 | * to transmit. |
| 841 | * |
| 842 | * @return The number of groups the FM driver actually accepted. |
| 843 | * A value >0 indicates the command was successfully |
| 844 | * accepted and a return value of "-1" indicates error. |
| 845 | * |
| 846 | * @see #transmitRdsGroupControl |
| 847 | */ |
| 848 | |
| 849 | public int transmitRdsContGroups(byte[] rdsGroups, long numGroupsToTransmit){ |
| 850 | /* |
| 851 | * This functionality is currently unsupported. |
| 852 | */ |
| 853 | return -1; |
| 854 | } |
| 855 | |
| 856 | /*============================================================== |
| 857 | FUNCTION: transmitRdsGroupControl |
| 858 | ==============================================================*/ |
| 859 | /** |
| 860 | * Pause/Resume RDS/RBDS group transmission, or stop and clear |
| 861 | * all RDS groups. |
| 862 | * <p> |
| 863 | * This is a function used to pause/resume RDS/RBDS |
| 864 | * group transmission, or stop and clear all RDS groups. This |
| 865 | * function can be used to control continuous and |
| 866 | * non-continuous RDS/RBDS group transmissions. This functionality |
| 867 | * is currently unsupported. |
| 868 | * <p> |
| 869 | * @param ctrlCmd The Tx RDS group control.This should be one of the |
| 870 | * contants RDS_GRPS_TX_PAUSE/RDS_GRPS_TX_RESUME/RDS_GRPS_TX_STOP |
| 871 | * |
| 872 | * @return true if RDS Group Control command was |
| 873 | * successfully sent to the driver, false if RDS |
| 874 | * Group Control command could not be sent to the |
| 875 | * driver. |
| 876 | * |
| 877 | * @see #rdsGroupControlCmdType |
| 878 | * @see #transmitRdsGroups |
| 879 | */ |
| 880 | public boolean transmitRdsGroupControl(int ctrlCmd){ |
| 881 | boolean bStatus = true; |
| 882 | /* |
| 883 | * This functionality is currently unsupported. |
| 884 | */ |
| 885 | int val = 0; |
| 886 | switch( ctrlCmd ) { |
| 887 | case RDS_GRPS_TX_PAUSE:break; |
| 888 | case RDS_GRPS_TX_RESUME:break; |
| 889 | case RDS_GRPS_TX_STOP:break; |
| 890 | default: |
| 891 | /*Shouldn't reach here*/ |
| 892 | bStatus = false; |
| 893 | } |
| 894 | return bStatus; |
| 895 | } |
| 896 | |
| 897 | /*============================================================== |
| 898 | FUNCTION: setTxPowerLevel |
| 899 | ==============================================================*/ |
| 900 | /** |
| 901 | * Sets the transmitter power level. |
| 902 | * |
| 903 | * <p> |
| 904 | * This is a function used for setting the power level of |
| 905 | * Tx device. |
| 906 | * <p> |
| 907 | * @param powLevel The Tx power level value to be set. The value should be |
| 908 | * in range 0-7.If input is -ve level will be set to 0 |
| 909 | * and if it is above 7 level will be set to max i.e.,7. |
| 910 | * |
| 911 | * @return true on success, false on failure. |
| 912 | * |
| 913 | */ |
| 914 | public boolean setTxPowerLevel(int powLevel){ |
| 915 | boolean bStatus = true; |
| 916 | int err = FmReceiverJNI.setTxPowerLevelNative( sFd, powLevel ); |
| 917 | if( err < 0 ){ |
| 918 | Log.d(TAG,"setTxPowerLevel is failure"); |
| 919 | return false; |
| 920 | } |
| 921 | return bStatus; |
| 922 | } |
| 923 | |
| 924 | /* |
| 925 | * getFMState() returns: |
| 926 | * '0' if FM State is OFF |
| 927 | * '1' if FM Rx is On |
| 928 | * '2' if FM Tx is On |
| 929 | * '3' if FM device is Searching |
| 930 | */ |
| 931 | public int getFMState() { |
| 932 | /* Current State of FM device */ |
| 933 | int currFMState = FmTransceiver.getFMPowerState(); |
| 934 | return currFMState; |
| 935 | } |
| 936 | }; |