8

I am facing a problem with the IR emitter on my Galaxy S5 running under Android 5.0.

Before I updated it to 5.0, my app was perfectly working on my phone but now, the device I am suppose to manage has no reaction. When I click on my app to send an IR code, the led blinks to indicate that the IR manager is activated and I can receive a signal with a IR photodiode connected to my scope. Unfortunately, the shape of the signal I get is very different from what it should be.

I can add that the same code running on my tablet under Android 4.4.2 still works perfectly.

To help in answering my question, a sample of my code :

private String commande="0000 0070 0000 0032 0080 003F 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 "
+ "0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 "
+ "0030 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0030 0010 0030 "
+ "0010 0010 0010 0010 0010 0010 0010 0030 0010 0030 0010 0030 0010 0030 0010 0030 0010 0010 0010 0030 0010 0A98";

IRManager=(ConsumerIrManager)activité.getSystemService(Context.CONSUMER_IR_SERVICE);
code=commandConversion(commande);
IRManager.transmit(code.getFrequency(),code.getCodes());

private RemoteCommandeCode commandConversion(String command) {
    List<String> list;
    RemoteCommandeCode code;
    int frequency;

    list= new ArrayList<String>(Arrays.asList(command.split(" ")));

    list.remove(0); // dummy

    frequency = Integer.parseInt(liste.remove(0), 16); // frequency

    list.remove(0); // seq1

    list.remove(0); // seq2

    code=new RemoteCommandeCode(list.size());

    for (int i = 0; i < list.size(); i++) {
        code.setCode(i,Integer.parseInt(list.get(i), 16));
    }

    frequency = (int) (1000000 / (frequency * 0.241246));

    code.setFrequency(frequency);

    return(code);
}

public class RemoteCommandeCode {
    private int fréquence;
    private int [] codes;

    public RemoteCommandeCode(int nombreCodes){
        codes=new int[nombreCodes];
    }

    public int getFrequency() {
        return frequency;
    }

    public void setFrequency(int frequency) {
        this.frequency = frequency;
    }

    public int [] getCodes() {
        return codes;
    }

    public void setCodes(int [] codes) {
        this.codes = codes;
    }

    public void setCode(int i,int code){
        codes[i]=code;
    }
}

As asked, images of the signal emitted with the simple code "0000 0070 0000 0003 0010 0020 0010 0020 0010 0020", I get on 4.4.2 : Signal on Android 4.4.2

and on Android 5.0 : Signal on Android 5.0

VD63
  • 133
  • 1
  • 9
  • What we would really need to see would be plots of the old vs. the new, or even better yet, a very simple pattern which is not transmitted by the new version as it should be. – Chris Stratton Mar 01 '15 at 14:58
  • Pictures of the signal emitted added in the question... – VD63 Mar 02 '15 at 16:47
  • Your timebase is too slow to verify details, but it seems pretty clear that the second plot is a near total failure. Perhaps you can see if there is any other app or demo which is able to transmit more plausible waveforms on the newer version? Is this an official Samsung build of 5.0 delivered OTA to your device, or something you sourced on your own or a custom ROM/port? – Chris Stratton Mar 02 '15 at 17:24
  • The new version is totally official and was downloaded through my phone service provider. I can add that the application "smart remote" is still perfectly able to control my devices. – VD63 Mar 03 '15 at 16:02
  • 2
    I am also having this problem, but you have way more sophisticated resources than I to investigate this. From my user-base, I've also noticed this happening on HTC One M8 devices running stock Android 5.0 roms. The symptoms for me seem to be very similar; usually it takes a few milliseconds-a second to transmit a code, but since Android 5.0 it immediately jumps past the transmit code without throwing an exception. – Dwebtron Mar 09 '15 at 03:38
  • 1
    According to the link supplied by Dwebtron, the problem comes from the difference in the data coding since 4.4.3. Before 4.4.3, the IR data was expressed in periods of the carrier frequency and after, it is expressed directly in µs. With this correction made, I now get the pulse width I want, but I still have a problem. The carrier frequency is set to 37000Hz, with an IR emitter capable of emitting in the range 16000-60000Hz, but I don't get any modulation. "ON" periods are characterized by a continuous lighting, and not by the light being modulated at 37kHz. It seems another bug exists... – VD63 Mar 15 '15 at 08:24

1 Answers1

3

This method will fix the IR problems for all Android versions

/*
 * preforms some calculations on the codesets we have in order to make them work with certain models of phone.
 *
 * HTC devices need formula 1
 * Samsungs want formula 2
 *
 * Samsung Pre-4.4.3 want nothing, so just return the input data
 *
 */
private static int[] string2dec(int[] irData, int frequency) {
    int formula = shouldEquationRun();

    //Should we run any computations on the irData?
    if (formula != 0) {
        for (int i = 0; i < irData.length; i++) {
            if (formula == 1) {
                irData[i] = irData[i] * (1000000/frequency);//the brackets should avoid an arithmetic overflow
            } else if (formula == 2) {
                irData[i] = (int) Math.ceil(irData[i] * 26.27272727272727); //this is the samsung formula as per http://developer.samsung.com/android/technical-docs/Workaround-to-solve-issues-with-the-ConsumerIrManager-in-Android-version-lower-than-4-4-3-KitKat
            }
        }
    }
    return irData;
}

/*
 * This method figures out if we should be running the equation in string2dec,
 * which is based on the type of device. Some need it to run in order to function, some need it NOT to run
 *
 * HTC needs it on (HTC One M8)
 * Samsung needs occasionally a special formula, depending on the version
 * Android 5.0+ need it on. 
 * Other devices DO NOT need anything special.
 */
private static int shouldEquationRun() {
    //Some notes on what Build.X will return
    //System.out.println(Build.MODEL); //One M8
    //System.out.println(Build.MANUFACTURER); //htc
    //System.out.println(Build.VERSION.SDK_INT); //19

    //Samsung's way of finding out if their OS is too new to work without a formula:
    //int lastIdx = Build.VERSION.RELEASE.lastIndexOf(".");
    //System.out.println(Build.VERSION.RELEASE.substring(lastIdx+1)); //4

    //handle HTC
    if (Build.MANUFACTURER.equalsIgnoreCase("HTC")) {
        return 1;
    }
    //handle Lollipop (Android 5.0.1 == SDK 21) / beyond
    if (Build.VERSION.SDK_INT >= 21) {
        return 1;
    }
    //handle Samsung PRE-Android 5
    if (Build.MANUFACTURER.equalsIgnoreCase("SAMSUNG")) {
        if (Build.VERSION.SDK_INT >= 19) {
            int lastIdx = Build.VERSION.RELEASE.lastIndexOf(".");
            int VERSION_MR = Integer.valueOf(Build.VERSION.RELEASE.substring(lastIdx + 1));
            if (VERSION_MR < 3) {
                // Before version of Android 4.4.2
                //Note: NO formula here, not even the other one
                return 0;
            } else {
                // Later version of Android 4.4.3
                //run the special samsung formula here
                return 2;
            }
        }
    }
    //if something else...
    return 0;
}

*Edit: Thanks to the OP's help, I was able to figure out how to fix this. This answer should now solve this problem.

root32
  • 3
  • 2
Dwebtron
  • 777
  • 13
  • 27
  • According to the link you supplied, the problem comes from the difference in the data coding since 4.4.3. Before 4.4.3, the IR data was expressed in periods of the carrier frequency and since 4.4.3, it is expressed directly in µs. With this correction made, I now get the pulse width I want. Thanks! – VD63 Mar 15 '15 at 08:23
  • What do you @VD63 mean "it is expressed directly in µs"? I'm not completely familiar with IR stuff in general.... Is there something quick I can add to that above method to fix it? Is there something you can point me to so I can read up on it? Thanks for letting me know that helped you, by the way. :) – Dwebtron Mar 15 '15 at 21:31
  • Before 4.4.3, the numbers is the sequence ""0000 0070 0000 0032 0080 003F 0010..." represent the number of carrier period the On or OFF pulses are supposed to last. Since 4.4.3, this same sequence represents numbers of microseconds, and that's why a conversion is necessary. To pass from before to after, you have to divide your numbers by the carrier frequency, which will give you the result in seconds, and to multiply it by 1000000 to get it in microseconds. – VD63 Mar 16 '15 at 16:30
  • I'm still having some trouble with this.... Could you be a little more specific? I don't know much about the IR stuff, I just know what I've googled and figured out over the last ~6-12 months. Are my equations in the answer above still accurate? Is there a new one I should be running? Is there one of those that always should run? How did you fix it? – Dwebtron Apr 07 '15 at 01:18
  • Your formula #1 is exactly the one I described to pass from duration in carrier period to microseconds. For your formula #2, I am not sure about the signification of the number 26.272, but It could be formula #1 applied with a carrier frequency of 38062Hz. So I think you can work only with formula #1 when running on a system above 4.4.2. – VD63 Apr 07 '15 at 16:19
  • Thanks again for your help. I updated my answer with the code that solved the problem for me, so that others can see what the heck we're talking about ;) – Dwebtron Apr 24 '15 at 01:55
  • Essentially, the code uses 38062 Hz if it's a Samsung device. 1000000 / 38062 = 26.27272727272727 – X-Ray Apr 26 '15 at 02:06