@@ -407,10 +407,10 @@ rg_app_t *rg_system_init(int sampleRate, const rg_handlers_t *handlers, void *_u
407407 .speed = 1.f ,
408408 .sampleRate = sampleRate ,
409409 .tickRate = 60 ,
410+ .tickTimeout = 3000000 ,
410411 .frameTime = 1000000 / 60 ,
411412 .frameskip = 1 , // This can be overriden on a per-app basis if needed, do not set 0 here!
412413 .overclock = 0 ,
413- .tickTimeout = 3000000 ,
414414 .lowMemoryMode = false,
415415 .enWatchdog = true,
416416 .isColdBoot = true,
@@ -1093,6 +1093,11 @@ int rg_system_get_log_level(void)
10931093void rg_system_set_overclock (int level )
10941094{
10951095#if CONFIG_IDF_TARGET_ESP32
1096+ if (level < -5 || level > 6 )
1097+ {
1098+ RG_LOGW ("Invalid level %d, min:-4 max:3" , level );
1099+ return ;
1100+ }
10961101 // #include "driver/uart.h"
10971102 // None of this is documented by espressif but there are comments to be found in the file `rtc_clk.c`
10981103 #define I2C_BBPLL 0x66
@@ -1107,66 +1112,70 @@ void rg_system_set_overclock(int level)
11071112 extern void rom_i2c_writeReg (uint8_t block , uint8_t host_id , uint8_t reg_add , uint8_t data );
11081113 extern uint8_t rom_i2c_readReg (uint8_t block , uint8_t host_id , uint8_t reg_add );
11091114 extern int uart_set_baudrate (int uart_num , uint32_t baud_rate );
1110-
1111- static uint8_t BASE_ENDIV5 , BASE_BBADC_DSMP , BASE_BBADC_OC_LREF , BASE_BBADC_OC_DIV_7_0 , BASE_BBADC_OC_DCUR ;
1112- static bool BASE_SAVED = false;
1113- if (!BASE_SAVED )
1115+ extern uint64_t esp_rtc_get_time_us (void );
1116+
1117+ uint8_t PREV_ENDIV5 = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_ENDIV5 );
1118+ uint8_t PREV_BBADC_DSMP = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_BBADC_DSMP );
1119+ uint8_t PREV_BBADC_OC_LREF = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_LREF );
1120+ uint8_t PREV_BBADC_OC_DIV_7_0 = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_DIV_7_0 );
1121+ uint8_t PREV_BBADC_OC_DCUR = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_DCUR );
1122+ // It's important that the PLL is set at 480Mhz because we make many assumptions based on this.
1123+ // Not so much the speed itself, but the many related registers as well as the core voltage and current.
1124+ if (PREV_ENDIV5 != BBPLL_ENDIV5_VAL_480M || PREV_BBADC_DSMP != BBPLL_BBADC_DSMP_VAL_480M )
11141125 {
1115- BASE_ENDIV5 = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_ENDIV5 );
1116- BASE_BBADC_DSMP = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_BBADC_DSMP );
1117- BASE_BBADC_OC_LREF = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_LREF );
1118- BASE_BBADC_OC_DIV_7_0 = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_DIV_7_0 );
1119- BASE_BBADC_OC_DCUR = rom_i2c_readReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_DCUR );
1120- BASE_SAVED = true;
1121- }
1122-
1123- uint8_t ENDIV5 = BASE_ENDIV5 ;
1124- uint8_t BBADC_DSMP = BASE_BBADC_DSMP ;
1125- uint8_t BBADC_OC_LREF = BASE_BBADC_OC_LREF ;
1126- uint8_t BBADC_OC_DIV_7_0 = BASE_BBADC_OC_DIV_7_0 ;
1127- uint8_t BBADC_OC_DCUR = BASE_BBADC_OC_DCUR ;
1128-
1129- if (level < -4 || level > 3 )
1130- {
1131- RG_LOGW ("Invalid level %d, min:-4 max:3" , level );
1126+ RG_LOGE ("Expected to find a 480Mhz PLL." );
11321127 return ;
11331128 }
1134- else if (level != 0 )
1135- {
1136- uint8_t div_ref = 0 ;
1137- uint8_t div7_0 = (level + 4 ) * 8 ;
1138- uint8_t div10_8 = 0 ;
1139- uint8_t lref = 0 ;
1140- uint8_t dcur = 6 ;
1141- uint8_t bw = 3 ;
1142- ENDIV5 = BBPLL_ENDIV5_VAL_480M ;
1143- BBADC_DSMP = BBPLL_BBADC_DSMP_VAL_480M ;
1144- BBADC_OC_LREF = (lref << 7 ) | (div10_8 << 4 ) | (div_ref );
1145- BBADC_OC_DIV_7_0 = div7_0 ;
1146- BBADC_OC_DCUR = (bw << 6 ) | dcur ;
1147- }
1129+
1130+ uint8_t div_ref = 0 ;
1131+ uint8_t div7_0 = 28 + (level * 5 );
1132+ uint8_t div10_8 = 0 ;
1133+ uint8_t lref = 0 ;
1134+ uint8_t dcur = 6 ;
1135+ uint8_t bw = 3 ;
1136+ uint8_t ENDIV5 = BBPLL_ENDIV5_VAL_480M ;
1137+ uint8_t BBADC_DSMP = BBPLL_BBADC_DSMP_VAL_480M ;
1138+ uint8_t BBADC_OC_LREF = (lref << 7 ) | (div10_8 << 4 ) | (div_ref );
1139+ uint8_t BBADC_OC_DIV_7_0 = div7_0 ;
1140+ uint8_t BBADC_OC_DCUR = (bw << 6 ) | dcur ;
11481141
11491142 RG_LOGW (" " );
1150- RG_LOGW ("BASE: %d %d %d %d %d" , BASE_ENDIV5 , BASE_BBADC_DSMP , BASE_BBADC_OC_LREF , BASE_BBADC_OC_DIV_7_0 , BASE_BBADC_OC_DCUR );
1143+ RG_LOGW ("BASE: %d %d %d %d %d" , PREV_ENDIV5 , PREV_BBADC_DSMP , PREV_BBADC_OC_LREF , PREV_BBADC_OC_DIV_7_0 , PREV_BBADC_OC_DCUR );
11511144 RG_LOGW ("NEW : %d %d %d %d %d" , ENDIV5 , BBADC_DSMP , BBADC_OC_LREF , BBADC_OC_DIV_7_0 , BBADC_OC_DCUR );
11521145 RG_LOGW (" " );
1146+ rg_task_delay (20 );
11531147
1154- RG_LOGW ("Preparing peripherals for the speed change..." );
1155- rg_task_delay (10 ); // Wait for the log to be sent
1156-
1157- float overclock_ratio = (240 + (level * 40 )) / 240.f ;
1158- rg_audio_set_sample_rate (app .sampleRate / overclock_ratio );
1159- uart_set_baudrate (0 , 115200 / overclock_ratio );
1160-
1161- RG_LOGW ("Updating clock registers!" );
1162- rom_i2c_writeReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_ENDIV5 , ENDIV5 );
1163- rom_i2c_writeReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_BBADC_DSMP , BBADC_DSMP );
1148+ // rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_ENDIV5, ENDIV5);
1149+ // rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_BBADC_DSMP, BBADC_DSMP);
11641150 // rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_LREF, BBADC_OC_LREF);
11651151 rom_i2c_writeReg (I2C_BBPLL , I2C_BBPLL_HOSTID , I2C_BBPLL_OC_DIV_7_0 , BBADC_OC_DIV_7_0 );
11661152 // rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DCUR, BBADC_OC_DCUR);
1167- RG_LOGW ("Overclock applied!" );
1153+
1154+ // RTC clock isn't affected by the CPU or APB clocks, so it remains our only reliable time measurement
1155+ uint64_t t = esp_rtc_get_time_us (); // The - 10000 is to account for time wasted on mutexes
1156+ uint32_t cc = xthal_get_ccount (); // Obtain it *after* calling esp_rtc_get_time_us because it is slow
1157+ rg_usleep (100000 );
1158+ int real_mhz = (double )(xthal_get_ccount () - cc ) / (esp_rtc_get_time_us () - t );
1159+ int calc_mhz = 240 + level * 20 ;
1160+
1161+ // Most audio devices rely on either the APB or the CPU clocks, which we've just skewed. So we have to
1162+ // compensate. The external DAC uses the APLL which is an independant clock source, no need to correct.
1163+ if (strcmp (rg_audio_get_sink ()-> name , "Ext DAC" ) != 0 )
1164+ rg_audio_set_sample_rate (app .sampleRate * (240.0 / real_mhz ));
1165+ uart_set_baudrate (0 , 115200.0 * (240.0 / real_mhz ));
1166+ // esp_timer_impl_update_apb_freq(80.0 / 240.0 * real_mhz);
1167+ // ets_update_cpu_frequency(real_mhz);
1168+
1169+ // This is a lazy hack to report a more accurate emulation speed. Obviously this isn't a real solution.
1170+ static int original_tickRate = 0 ;
1171+ if (!original_tickRate )
1172+ original_tickRate = app .tickRate ;
1173+ app .tickRate = original_tickRate * (240.f / real_mhz );
11681174
11691175 app .overclock = level ;
1176+ app .frameskip = 1 ;
1177+
1178+ RG_LOGW ("Overclock level %d applied: %dMhz (measured: %dMhz)" , level , calc_mhz , real_mhz );
11701179#else
11711180 RG_LOGE ("Overclock not supported on this platform!" );
11721181#endif
0 commit comments