o-gs / dji-firmware-tools

Tools for handling firmwares of DJI products, with focus on quadcopters.
GNU General Public License v3.0
1.59k stars 426 forks source link

Power zone (FCC/CE) in GL300a/b/c RC Firmware #10

Open MrBurnsAT opened 7 years ago

MrBurnsAT commented 7 years ago

RC Firmware must be changeable too.

Some limitations was added with RC Firmwares 1.6 and newer. Output Power is reduced from 25mW to 10mW in CE Mode.

And It should be possible to change CE to FCC Mode (RC Checks via GPS location and Sets than FCC or CE Mode, USA = FCC, Europe = CE

KennethMcNutt commented 7 years ago

Just need them both on? then attenuate the signal.. Bt shielding the craft somehow.. (No need for flight?? )

This guy is got a lot of info on how to test and theory!! On how R/C control works.. https://www.youtube.com/watch?v=AkK3R1CD3RQ (he has MANY!!)

rulppa commented 7 years ago

It doesnt work thay way, signal does no go up when distance increases, anyway tested it.

If you pair correct model inspire1 remote with correct fw in it, remote pairs with approx 80mW power. With GPS lock, without GPS lock (to phantom 3a/p).

These controllers were banned atleast on my country, before there was fw update to get power down to CE norms. These are the remotes people are asking crazy prices if they are on correct fw.

rulppa commented 7 years ago

After fw update, those Inspire1 remotes still pairs with more mW with Inspire1, but when paired with phantom3a/p mW goes down. I think @Mefistotelis should be able to find this from fw.

KennethMcNutt commented 7 years ago

Ok, understandable. My info comes from P3S..... It has a script in the controller. It Increases the db when the signal is lost.. (Magic Power Mod..) It was assuming the controller did not use telemetry to increase db I guess I thought that it would use some sort of RSSI...?

mefistotelis commented 7 years ago

I could try to compare the Inspire firmwares, but I'd need to know at which version the power was decreased.

KennethMcNutt commented 7 years ago

@rulppa "These are the remotes people are asking crazy prices if they are on correct fw." What firmware are they looking for?? 1.5.8?? lower?? I am interested in the Why? (range only?) Do they have a exact preference? On the firmware Version? A/C R/C ??

polarisax commented 7 years ago

Is there any chance (by FW or HW mods) to bring the power of the radio control to the max? I think it is 100mW...

mefistotelis commented 7 years ago

I am interested in the Why? (range only?)

I don't know why, but I can confirm that any Inspire RCs are at least 4x more costly than Phantom's. I assumed that this is because Inspire pilots are more often experienced people -> crashes are less frequent -> there's less stand-alone RCs on the market. It might also be due to the fact that with each Inspire you can use 2 RCs with one drone.

CirConFleX commented 7 years ago

@polarisax This is what people are trying to do on this topic.

KennethMcNutt commented 7 years ago

I need to interject... I know that P3S and P3P have little in common... But The creator of the Magic Power mod and I have just recently proven that the P3S Tx Db is set at 27 db... (in the USA) That being said... I have two questions!!!??? If the Fcc is limiting these drones to 20db?? Why are they allowing 27dB?? I don't know how many here know about the "CE to FCC" mod for the P3S and the "DANGERS" of 27db but it was wrong I have the proof you can confirm it... So..... How this relates??? Well, If the P3S is not conforming to this FCC standard??? Why would the P3P??? https://www.facebook.com/groups/1660074954208418/permalink/1857032987845946/

KyokushinPL commented 7 years ago

@MrBurnsAT In my country - Poland, a member of EU - a limitation is 100mW (20dB). I do not heard of any changes in EU rules. Nobody knows why DJI limited it to 16dBm, however its not caused by regulations, and never heard about new regulations which could limit it to 10mW. There is a few topics about measuring output power, it is not so simple because power output is dynamically changed: http://forum.dji.com/thread-51503-1-1.html http://forum.dji.com/thread-56271-1-1.html In fact CE users have an issues with range.

DJI employee confirmed here there was not lowering of power: http://forum.dji.com/forum.php?mod=viewthread&tid=51503&page=1#pid398234 http://forum.dji.com/forum.php?mod=viewthread&tid=51503&page=2#pid398916

As far i know they chenged in 1.6 something with encryption and securit, and maybe that change could influe on range.

pawelsky commented 7 years ago

@mefistotelis Just got one an idea to look into the CANbus port on the transmitter's HDMI module, to see if there is any special communication when the homepoint is stored that could be interpreted as the mode change.

Will give it a go and report back.

mefistotelis commented 7 years ago

Oh, I didn't even knew the "reserved" port is a CANbus.

Thank you @pawelsky, that will be helpful.

pawelsky commented 7 years ago

Unfortunately the RC CANbus port seems to be completely quiet (at least on 1.8.0, 1.6.0 and 1.5.8) :(

Will try with earlier firmwares (just need to practice the downgrade trick on Android).

EDIT: Silence on 1.4.3 as well. Looks like a dead end :(

Next thing to try is the CANbus in the bird itself, this one is more 'talkative'

pawelsky commented 7 years ago

Did some tests today listening to the serial communication (easier to decode than CANbus) going from the mainboard to the P3A OFDM module, but did not find anything obvious that would set the FCC/CE mode when the homepoint is set.

I did however find messages that contain information about GPS coordinates. I've also measured the output power of the OFDM module I was getting about 4.4mW.

Now, my plan now is to check whether providing fake coordinates (from FCC region) will change anything in the output power of the OFDM module...

My assumption is that it doesn't actually matter whether we check the transmitter or the OFDM module in P3A, they should both be changing the mode depending on location.

mefistotelis commented 7 years ago

Nice progress!

And I agree, it is also my understanding that either OFDM module or flight controller sets the coords for both drone and RC.

Within the RC, I found a code which I suspect sets the zone (it's just a suspicion, and the variable name was set by me):

void sub_4016(void *packet)
{
  unsigned int v1;
  int v2;
  char v3;

  zone_is_fcc = *((_BYTE *)packet + 11);
  v1 = *((_BYTE *)packet + 8);
  if ( ((v1 >> 5) & 3) == 2 )
  {
    *((_BYTE *)packet + 8) = v1 | 0x80;
    v3 = 0;
    sub_2C26(packet, &v3, 1, &v2);
    sub_2BD2(&v2);
  }
  JUMPOUT(&loc_3850);
}

The above function is called when packet[10]=32, packet[9]=6 and (packet[5] & 0x1F) is either 14, 20 or 31.

pawelsky commented 7 years ago

Hmmm... that rings a bell.

One of the messages I've seen coming from the OFDM to mainboard is:

55 14 04 6D 0E 03 EF 23 20 06 1C 00 18 28 E1 07 05 19 22 05

This is in HEX: 55 is the message start 14 is the message len 6D 0E is some kind of message ID last 2 are CRC

Note that I've marked 5th (0x0E = 14 decimal), 9th (0x20 = 32 decimal) and 10th (0x06 = 6 decimal) byte in the message bold

I know that indexing should start from 0 (so this is all shifted by 1) and 10th and 9th are swapped compared to what you've described but...

I've only seen this message just after the transmitter is switched ON and the connection is established. Coincidence?

mefistotelis commented 7 years ago

It is somewhat similar, but the positions have to match exactly.

Btw, I found the code where packets are created:

struct UnknPacket1 {
  uint8_t field_0;
  uint16_t field_1;
  uint8_t field_3;
  uint8_t field_4;
  uint8_t field_5;
  uint16_t field_6;
  uint8_t field_8;
  uint8_t field_9;
  uint8_t field_A;
  uint8_t field_B;
};

void sub_2C26(struct UnknPacket1 *packet, void *payload, int payload_len, struct UnknPacket1 *outpckt)
{
  uint16_t chksum;

  outpckt->field_0 = 85;
  // Clear higher part of the outpckt[1]
  outpckt->field_1 ^= outpckt->field_1 & 0xFC00;
  // Set the higher part value to 1
  outpckt->field_1 |= (1 << 10) & 0xFC00;
  // Set the lower part value (packet size)
  packet_set_length(outpckt, 13 + payload_len);
  // outpckt[3] is the checksum of 3 preceding bytes
  outpckt->field_3 = compute_buf_checksum_xor1(0x77, outpckt, 3);
  // Copy all the fields of the packet
  outpckt->field_4 = outpckt->field_4 & 0x1F;
  outpckt->field_4 = outpckt->field_4 & 0xE0 | packet->field_5 & 0x1F;
  outpckt->field_5 = packet->field_4;
  outpckt->field_6 = packet->field_6;
  outpckt->field_8 = packet->field_8;
  outpckt->field_9 = packet->field_9;
  outpckt->field_A = packet->field_A;
  // optimized mem copy, looks complicated but is just copying
  memcpy(&outpckt->field_B, payload, payload_len);
  // Compute and store whole packet checksum
  chksum = compute_buf_checksum_xor2(outpckt, packet_get_length(outpckt) - 2, 0x3692);
  packet_set_checksum((unsigned char *)outpckt + packet_get_length(outpckt) - 2, chksum);
}

void packet_set_checksum(unsigned char *buf, uint16_t chksum)
{
  if (buf != NULL)
    *(uint16_t *)buf = chksum;
}

inline uint16_t packet_get_length(struct UnknPacket1 *outpckt)
{
  return (outpckt->field_1 & 0x3FF);
}

inline void packet_set_length(struct UnknPacket1 *outpckt, uint16_t len)
{
  outpckt->field_1 = outpckt->field_1 & 0xFC00 | len & 0x3FF;
}

const uint8_t arr_2A103[] = {
// table of 256 values
};

uint32_t compute_buf_checksum_xor1(uint32_t seed, uint8_t *buf, uint32_t len)
{
  uint32_t chksum;
  chksum = seed;
  while (len > 0)
  {
    chksum = arr_2A103[(*buf) ^ chksum];
    len--;
    buf++;
  }
  return chksum;
}

const uint16_t arr_2A808[] = {
// normal CRC16 table, 256 values
};

uint32_t compute_buf_checksum_xor2(uint8_t *buf, uint32_t len, uint32_t seed)
{
  uint32_t chksum;
  chksum = seed;
  if (buf == NULL)
    return 0xFFFF;
  while (len > 0)
  {
    chksum = arr_2A808[(uint8_t)((*buf) ^ chksum)] ^ (chksum >> 8);
    len--;
    buf++;
  }
  return chksum;
}

EDIT: updated the code.

mefistotelis commented 7 years ago

Ha, looking for the missing arrays, I was able to figure out base address of the binary - it's 0xa000.

I was looking for this address for days in the past and wasn't able to find it.

pawelsky commented 7 years ago

Nice, that connects some missing dots. I'll map that to the simplest messages that I've observed (e.g. setting the max altitude) from UI and chceck what field_B may be.

mefistotelis commented 7 years ago

This looks like the same format which @GlovePuppet firgured out for FC-ESC communication in issue #25.

pawelsky commented 7 years ago

Yes format is the same for pretty much all the messages (not only on serial but also on CANbus, e.g. for battery communication that I've been simulating to use non-smart battery), and it is the payload that makes a difference.

However I'm very interested what is the meaning of the packet_B byte as it seems to have special treatment and the "set" message seems to be the simplest one to manipulate and find out. Not that it would be critical for this particular issue, but I'm just curious.

GlovePuppet commented 7 years ago

Yeah, it's just the same as all the others, the payload starts at the 11th (B) byte.

I have a couple of handy tools for logging the serial bus, a piece of Python code that collects data from two UARTs and stuffs them into a FIFO that Wireshark can understand and a very early/rough Wireshark dissector. If anyone is interested I could polish up the dissector and make both available

pawelsky commented 7 years ago

I'm less advanced and stick to console which i fed with data from CANbus/Serial via Teensy 3.6 console

GlovePuppet commented 7 years ago

< joke > I hate to break it to you but the wheel has already been invented < / joke >

mefistotelis commented 7 years ago

Well, give us the script then!

GlovePuppet commented 7 years ago

Heheh, patience Grasshopper, I'm at work ...

pawelsky commented 7 years ago

So I "teleported" myself to FCC area by capturing the data stream coming from the mainboards to the OFDM module and replacing the GPS coordinates (in two messages, one reporting the current position and one storing the home position) on the fly. DJI Go app placed me on the map somewhere in Wisconsin, and welcomed me with the GEO warning from a nearby airfield, so I was sure the "teleportation" worked correctly.

Unfortunately the ODFM module output power measurements were not conclusive, they did change between 7mW and 13mW but this did not seem to be dependent on the location.

I need to do some more tests and analyze the logs recorded tomorrow.

EDIT: Done more tests and can confirm that the power of the ODFM does not change just based on the GPS coordinates/homepoint alone. The change must be initiated by the mainboard with a separate message, but to confirm that I would have do dismantle my whole P3A (something I would prefer to avoid) to get access to GPS and fake the coordinates at the source :(

KyokushinPL commented 7 years ago

OK folks, we got 2 of 3 goals (nfz/height) but last is force FCC mode. Do you know in which of extracted files some config may be stored?

mefistotelis commented 7 years ago

Currently we are stuck and need a step back.

We cannot confirm when we are in FCC and when in CE mode. We need to see the difference between these modes to get any further.

pawelsky commented 7 years ago

Just to give some update: I did eventually open my P3A to get access directly to the GPS and was modifying the GPS coordinates on the fly to put myself into the FCC area, but again I did not observe any significant change in the OFDM module transmit power (~25mW was the maximum I could get), which suggests that the power indeed scales with distance. As mefistotelis said we need to find an good indicator that would tell us whether we are in FCC or CE mode.

Fun fact: I did notice an interesting thing - the output antenna seems to change depending on the quad orientation compared to the homepoint. Clever :)

pawelsky commented 7 years ago

I just did some experiment. Having the RC connected to the PC via the micro USB socket I've sent a message that matches the requirements described in https://github.com/mefistotelis/phantom-firmware-tools/issues/10#issuecomment-303865138

550e04660a0e3827400620 01 67b5

Can't tell whether it does anything to the transmit power settings (sent my RF meter for calibration) but at least the RC understood the command and responded with

550e04660e0a3827c00620 00 28f0

@mefistotelis did you have a chance to find out what sub_2C26 and sub_2BD2 actually do?

GlovePuppet commented 7 years ago

Which RC model are you using? One easy test might be to monitor current consumption to determine if TX power changes.

pawelsky commented 7 years ago

I'm using B and C.

Another interesting thing is that when I first call the 0x20 command mentioned earlier with payload 00 and then call 0xF0 command (some kind of status I guess) I'm getting 5514046D0E0A4D27C006F0 **00**0AC000000000 2C64

If I then send the 0x20 command with payload 01, after 0xF0 command I'm getting 5514046D0E0A4B27C006F0 **E6**0AC000000000 B419

Notice the marked byte that changes value from 00 to E6. Wonder if we could use that as an indication of the FCC mode?

GlovePuppet commented 7 years ago

@mefistotelis Which version of which binary are you reversing? Can you share the IDB/C? I could take a look for the cmd handlers

pawelsky commented 7 years ago

Another interesting command is 0x01 (from the 0x06 command set) which returns position of all the sticks, e.g: 552604d10e0a2927c00601 00000004010004020004030004040004050004060004070004 d929

I'll describe the exact structure later

pawelsky commented 7 years ago

And some more commands that the RC responds to (from the 0x00 Universal Command Set this time)

0x01 - not sure what it means yet 552C04360E0A747EC00001 00102E0000000000000000000000000000000C03000306000A044302000001 9378

0x0C - not sure what it means yet (just zeros in payload) 551304030E0A717EC0000C 000000000000 965C

0xFF - seems to be the HW type/FW version (payload translates to WM610 A7_1765 20160321/01) 552704150E0A757EC000FF 574D3631302041375F313736352032303136303332312F303100 03D1

mefistotelis commented 7 years ago

@mefistotelis did you have a chance to find out what sub_2C26 and sub_2BD2 actually do?

The sub_2C26 seem to be used for preparing an answer for a packet. The answer has most fields copied from source, but:

I will rename this function to packet_prepare_response().

For sub_2BD2 - there is only one possibility. It must be used to send the response.

pawelsky commented 7 years ago

And what is done with the zone_is_fcc variable? I don't see it used anywhere

mefistotelis commented 7 years ago

There is a command which reads this variable:

void cmd_exec_get_zone_3EBA(struct UnknPacket1 *pkt)
{
  struct UnknPacket1 response_pkt;
  int param_buf;

  if ( ((pkt->ack >> 5) & 3) == 2 )
  {
    pkt->ack |= 0x80;
    LOBYTE(param_buf) = zone_is_fcc;
    packet_prepare_response(pkt, & param_buf, 1, &response_pkt);
    packet_send(&response_pkt);
  }
  JUMPOUT(&loc_D742);
}

This command is for CMDSET=6 and CMD=33.

Besides that, there is a is read in two more places which I don't fully understand.

pawelsky commented 7 years ago

And do you happen to know under which conditions is this cmd_exec_sub_3EBA called (i.e. for what source/target/command ID)?

mefistotelis commented 7 years ago

Just updated my answer with that info :)

@GlovePuppet - sure, i can share my symbols. Will update the C1_*.idc available here: https://github.com/mefistotelis/phantom-firmware-tools/tree/master/symbols

pawelsky commented 7 years ago

Did a bit more testing, unfortunately I don't see the 32 command being sent by the flight controller even when the homepoint is set using fake GPS coordinates somewhere in USA.

What I can confirm is that whatever is set with 32 command can then be retrieved with 33 command (and it seems to survive the reboot of the RC.

mefistotelis commented 7 years ago

This is where the value is used, but I have no idea what it does. All the uses are in this one function:

code - Click to expand
void task_BK5811_worker(int a1, int a2, int a3, int a4)
{
  int tmpval1;
  unsigned int tmpval2;
  int tmpval3;
  unsigned int i;
  unsigned char tmpflags;
  enum OS_ERR oserr;

  oserr = a4;
  sub_134C4(a1, a2, a3);
  sub_219D2(268450822, 252);
  byte_10003E21 = 0;
  byte_10003E22 = 0;
  sub_219D2(&byte_10003E21, 256);
  OSTimeDlyHMSM(0, 0, 1u, 0, 0, &oserr);
  for (i = 0; i < 10; ++i)
  {
    tmpval1 = sub_1273E();
    if ( sub_13B00(tmpval1) != 1 )
      break;
  }
  if ( i < 10)
    byte_1000000E &= ~0x08;
  else
    byte_1000000E |= 0x08;
  if ( i >= 10)
    BYTE1(dword_10000018) &= ~0x20;
  else
    BYTE1(dword_10000018) |= 0x20;

  while ( 1 )
  {
    if ( byte_10000002 )
    {
      tmpval2 = ((unsigned int)(unsigned __int8)byte_10003AE2 >> 2) & 3;
      if (tmpval2 != byte_1000022C)
      {
      switch (tmpval2)
      {
      case 1:
          tmpval3 = rf_power_unkn1(0);
          sub_1334C(tmpval3);
          dword_10000238 = dword_1000022F;
          dword_10003D02 = *(_DWORD *)&status_MYNAME;
          word_10003D06 = word_100005F3;
          status_MYPASSWORD = 1234;
          word_10003D08 = 1234;
          byte_10003D0A = status_STATUE;
          byte_10003D0C = status_GIMBAL_CTLIP;
          status_function = 0;
          sub_FD6C(3, "MASTER");
          break;
      case 2:
          tmpval3 = rf_power_unkn1(0);
          sub_133D8(tmpval3);
          dword_10000238 = dword_1000022F;
          status_MYIP = 1;
          status_function = 1;
          status_GROUP_PASSWORD = 1234;
          sub_FD6C(3, "SLAVER");
          break;
      }
      byte_1000022C = ((unsigned __int8)byte_10003AE2 >> 2) & 3;
      }
      goto LABEL_58;
    }

    if (zone_is_on != byte_1000022B)
    {
      if ( zone_is_on )
      {
        switch (status_function)
        {
        case 0:
            sub_1334C();
            break;
        case 1:
            sub_133D8();
            break;
        case 2:
            sub_1344E();
            break;
        }
      }
      else
      {
        v2009C03C |= 0x400u;
        v2009C01C |= 0x80000u;
        sub_1BCA2(20);
        sub_1BCA2(1);
        *(_DWORD *)&byte_10000244 = 0;
        word_10000248 = 0;
        byte_1000024A = 0;
      }
      byte_1000022B = zone_is_on;
    }

    if (zone_is_fcc != byte_1000022E)
    {
      switch (zone_is_fcc)
      {
      case 0:
        rf_power_unkn1(5);
        break;
      case 1:
        rf_power_unkn1(7);
        break;
      }
      byte_1000022E = zone_is_fcc;
    }

    if ( zone_is_on == 1 && (unsigned __int8)status_function != (unsigned __int8)byte_1000022D )
    {
      switch (status_function)
      {
      case 0:
          sub_1334C();
          break;
      case 1:
          sub_133D8();
          break;
      case 2:
          sub_1344E();
          break;
      }
      byte_1000022D = status_function;
    }

    if ( sub_217A8(&dword_10000238, &status_GROUP_ID, 4) && status_function )
      dword_10000238 = *(_DWORD *)&status_GROUP_ID;

    if (status_GIMBAL_CTLIP != byte_1000022A)
    {
      for (i = 0; i < 6; i++)
      {
        tmpflags = status_DEFVER[11 * i + 42];
        if ( (unsigned __int8)status_GIMBAL_CTLIP - 1 == i )
          tmpflags |= 0x10;
        else
          tmpflags &= ~0x10;
        status_DEFVER[11 * i + 42] = tmpflags;
      }
      byte_1000022A = status_GIMBAL_CTLIP;
    }

LABEL_58:
    sub_139DC();
    OSTimeDlyHMSM(0, 0, 0, 2u, 0, &oserr);
  }
  // The loop above never ends
}

Memory above x10000000 is some kind of shared hardware-mapped area.

EDIT: updated the code to be clearer. EDIT2: It turns out we were looking at the code which comes from P3C and is never used in P3X/P3S. Named the function accordingly.

pawelsky commented 7 years ago

Nice. Looks a bit like this is related to the Master/Slave connection between two RCs at the beginning, but then eventually RF power seems to be set.

Do you have the insides of rf_power_unkn1() function? Looks like it is called with either 7 or 5 depending of the value of zone_is_fcc.

Also sub_1334C() and sub_133D8() may be helpful as they do something with the result of rf_power_unkn1(0) call.

pawelsky commented 7 years ago

While waiting for my RF meter to come back from calibration I've checked the power consumption as suggested earlier by @GlovePuppet

One easy test might be to monitor current consumption to determine if TX power changes.

Unfortunately I don't see any change - it oscillates between 350-420mA regardless of the value set by CMD 32 :(

mefistotelis commented 7 years ago

Here's the function really used for P3X/P3S - the one before turned out to be for P3C only.

code - Click to expand
void __noreturn task_CC1120_worker(void *dtptr)
{
  int v2;
  int v3;
  int v4;
  int v5;
  unsigned int tmpval1;
  unsigned int i;
  unsigned int tmpflags;
  enum OS_ERR oserr;

  sub_142DE(dtptr);
  v2 = sub_219D2(268450822, 252);
  for (i=10; i > 0; i--)
  {
    v5 = sub_1432A(v2, v3, v4);
    if (sub_14360(v5))
      break;
  }

  if (i > 0)
    byte_1000000E &= ~0x08;
  else
    byte_1000000E |= 0x08;

  if (i > 0)
    BYTE1(dword_10000018) |= 0x20;
  else
    BYTE1(dword_10000018) &= ~0x20;

  sub_13FBC();

  while ( 1 )
  {

    if ( byte_10000002 )
    {
      tmpval1 = ((unsigned int)byte_10003AE2 >> 2) & 3;
      if (tmpval1 != byte_1000026E)
      {
        switch (tmpval1)
        {
        case 1:
            sub_14968();
            dword_10000238 = dword_1000022F;
            dword_10003D02 = *(_DWORD *)&status_MYNAME;
            word_10003D06 = word_100005F3;
            status_MYPASSWORD = 1234;
            word_10003D08 = 1234;
            byte_10003D0A = status_STATUE;
            byte_10003D0C = status_GIMBAL_CTLIP;
            status_function = 0;
            dbg_printf(1, "TestMaster");
            break;
        case 2:
            sub_149EE();
            dword_10000238 = dword_1000022F;
            status_MYIP = 1;
            status_function = 1;
            status_GROUP_PASSWORD = 1234;
            dbg_printf(1, "TestSlaver");
            break;
        }
        tmpval1 = ((unsigned int)byte_10003AE2 >> 2) & 3;
        byte_1000026E = tmpval1;
      }
      goto LABEL_51;
    }

    if (zone_is_on != byte_1000026C)
    {
      if ( zone_is_on )
      {
        switch (status_function)
        {
          case 1:
              sub_149EE();
              break;
          case 2:
              sub_14A9C();
              break;
          case 0:
              sub_14968();
              break;
        }
      } else
      {
        sub_1BCA2(20);
        sub_1BCA2(1);
        *(_DWORD *)&byte_10000244 = 0;
        word_10000248 = 0;
        byte_1000024A = 0;
      }
      byte_1000026C = zone_is_on;
    }

    if (zone_is_on == 1 && status_function != byte_1000026D)
    {
      switch (status_function)
      {
      case 0:
          sub_14968();
          dbg_printf(1, "Master");
          break;
      case 1:
          sub_149EE();
          dbg_printf(1, "Slaver");
          break;
      case 2:
          sub_14A9C();
          dbg_printf(1, "Monitor");
          break;
      }
      byte_1000026D = status_function;
    }

    if ( sub_217A8(&dword_10000238, &status_GROUP_ID, 4) && status_function )
      dword_10000238 = *(_DWORD *)&status_GROUP_ID;

    if (status_GIMBAL_CTLIP != byte_1000026B)
    {
      for (i = 0; i < 6; i++)
      {
        tmpflags = status_DEFVER[11 * i + 42];
        if (status_GIMBAL_CTLIP - 1 == i)
          tmpflags |= 0x10;
        else
          tmpflags &= ~0x10;
        status_DEFVER[11 * i + 42] = tmpflags;
      }
      byte_1000026B = status_GIMBAL_CTLIP;
    }
LABEL_51:
    sub_139DC();
    status_STATUE |= 0x38u;
    OSTimeDlyHMSM(0, 0, 0, 3u, 0, &oserr);
  }
}
pawelsky commented 7 years ago

@mefistotelis so no sign of zone_is_fcc here :( Any idea where the ouptut of dbg_printf is redirected? I guess we shall come back to trying to find the Europe coordinates in the RC firmware (note that the FC sends the GPS position as radians to the OFDM unit)

mefistotelis commented 7 years ago

Any idea where the ouptut of dbg_printf is redirected?

The function is empty. No string is saved. Must be a part of debug macro, not used in production firmwares.

I guess we shall come back to trying to find the Europe coordinates in the RC firmware

That is one of the options. I already tried that - not an easy task (or I just lack the proper mindset to find it). But now when I see where CC1120 driver is, I could try to match the code with TI datasheet, or even better - if TI provides a library to drive this transmitter, I could match it with what I see in firmware.

EDIT: CC1120 is a 900MHz transceiver. Looks like I'm still looking at P3C code, just the Japanese variation.

pawelsky commented 7 years ago

Maybe looking into the OFDM module firmware will help? The message with the GPS position has Command Set 0x03 and Command Id 0x43 and length 0x3F. Below you can find an example (before acquiring the actual GPS position). First 8 bytes of payload is a double representing LON (degrees decimal converted to radians), next 8 is a double representing LAT (radian). I've also marked the satellite count byte.

                               LON              LAT                                                 SAT
553F048F03090D01000343   0000000000000000 0000000000000000 00000000000000000200FEFF1104860011718000 00 000000F6000000001E8A080200   038D