Q:

integer wrap-around not really understood

I have the following piece of code which is called approximately 100 times per second
if (elapsed_centiseconds_mod_60000 < 59999) {
    ++elapsed_centiseconds_mod_60000;
} else {
    elapsed_centiseconds_mod_60000 = 0;
}
if (elapsed_centiseconds_mod_60000 % 6000 == 0) {
    ++elapsed_minutes;
}

The types of the variables and constants are
volatile uint16_t elapsed_centiseconds_mod_60000;
volatile uint8_t start_minute_mod_10;
const int8_t calibration_second = 5;

Then exactly once per second the following is called
int16_t get_phase_deviation(uint8_t current_second, uint8_t current_minute_mod_10) {
    int32_t deviation=
         (int32_t) elapsed_centiseconds_mod_60000 -
        ((int32_t) current_second        + (int32_t)600 - (int32_t)calibration_second) * (int32_t) 100 -
        ((int32_t) current_minute_mod_10 + (int32_t) 60 - (int32_t)start_minute_mod_10)* (int32_t)6000;
    deviation %= 60000;

    return (int16_t)(deviation<=30000? deviation: deviation-60000);
}

The idea of the code is to detect relative frequency error of two oscillators. However the code does not work as expected. It will start to output a deviation of zero. But once the elapsed centiseconds are one more than they should it will jump immediately to an output of 5537 which coincidences with 2^16 % 60000 + 1. I tried to cast the intermediate values to int32_t but still the issue sticks. Usually the issue appears after 100 seconds or 10 000 centiseconds. I suspect some wrap around issue but I fail to see it.
Has anyone any idea which term is causing this and why?

A:

You are incorrectly casting the return value of get_phase_deviation() as the range of deviation %= 60000 is -59999 to 59999 (not 0 to 59999). You should change the line:
 return (int16_t)(deviation<=30000? deviation: deviation-60000);

to correctly deal with deviation <= -30000 as is appropriate or change the return type to int32_t.
Looking at the specific cases to understand the numbers you were getting, assuming:
 calibration_second = 0;
 start_minute_mod_10 = 0;

Then for a perfect system get_phase_deviation() is returning:
 deviation = -420000; // As computed
 deviation %= 60000;  // == 0
 return 0;

If you are 1 centisecond ahead this changes to:
 deviation = -419999; // As computed
 deviation %= 60000;  // == -59999
 return (int16_t) (-59999);  // == 5537

