|
|
@@ -6,6 +6,9 @@
|
|
|
|
|
|
#include <flipper_format/flipper_format_i.h>
|
|
|
|
|
|
+void raw_sampling_worker_start(ProtoViewApp *app);
|
|
|
+void raw_sampling_worker_stop(ProtoViewApp *app);
|
|
|
+
|
|
|
ProtoViewModulation ProtoViewModulations[] = {
|
|
|
{"OOK 650Khz", FuriHalSubGhzPresetOok650Async, NULL},
|
|
|
{"OOK 270Khz", FuriHalSubGhzPresetOok270Async, NULL},
|
|
|
@@ -53,9 +56,14 @@ uint32_t radio_rx(ProtoViewApp* app) {
|
|
|
furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
|
|
|
furi_hal_subghz_flush_rx();
|
|
|
furi_hal_subghz_rx();
|
|
|
+ if (!app->txrx->debug_direct_sampling) {
|
|
|
|
|
|
- furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, app->txrx->worker);
|
|
|
- subghz_worker_start(app->txrx->worker);
|
|
|
+ furi_hal_subghz_start_async_rx(subghz_worker_rx_callback,
|
|
|
+ app->txrx->worker);
|
|
|
+ subghz_worker_start(app->txrx->worker);
|
|
|
+ } else {
|
|
|
+ raw_sampling_worker_start(app);
|
|
|
+ }
|
|
|
app->txrx->txrx_state = TxRxStateRx;
|
|
|
return value;
|
|
|
}
|
|
|
@@ -64,9 +72,13 @@ uint32_t radio_rx(ProtoViewApp* app) {
|
|
|
void radio_rx_end(ProtoViewApp* app) {
|
|
|
furi_assert(app);
|
|
|
if (app->txrx->txrx_state == TxRxStateRx) {
|
|
|
- if(subghz_worker_is_running(app->txrx->worker)) {
|
|
|
- subghz_worker_stop(app->txrx->worker);
|
|
|
- furi_hal_subghz_stop_async_rx();
|
|
|
+ if (!app->txrx->debug_direct_sampling) {
|
|
|
+ if(subghz_worker_is_running(app->txrx->worker)) {
|
|
|
+ subghz_worker_stop(app->txrx->worker);
|
|
|
+ furi_hal_subghz_stop_async_rx();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ raw_sampling_worker_stop(app);
|
|
|
}
|
|
|
}
|
|
|
furi_hal_subghz_idle();
|
|
|
@@ -84,3 +96,63 @@ void radio_sleep(ProtoViewApp* app) {
|
|
|
furi_hal_subghz_sleep();
|
|
|
app->txrx->txrx_state = TxRxStateSleep;
|
|
|
}
|
|
|
+
|
|
|
+/* ============================= Raw sampling mode =============================
|
|
|
+ * This is useful only for debugging: in this mode instead of using the
|
|
|
+ * subghz thread, we read in a busy loop from the GDO0 pin of the CC1101
|
|
|
+ * in order to get exactly what the chip is receiving. Then using the
|
|
|
+ * CPU ticks counter we fill the buffer of data with the pulses level
|
|
|
+ * and duration. */
|
|
|
+
|
|
|
+int32_t direct_sampling_thread(void *ctx) {
|
|
|
+ ProtoViewApp *app = ctx;
|
|
|
+ bool last_level = false;
|
|
|
+ uint32_t last_change_time = DWT->CYCCNT;
|
|
|
+
|
|
|
+ while(app->txrx->ds_thread_running) {
|
|
|
+ uint32_t d[10];
|
|
|
+ for (uint32_t j = 0; j < 500; j++) {
|
|
|
+ uint32_t maxloops = 50000;
|
|
|
+ while(maxloops-- && app->txrx->ds_thread_running) {
|
|
|
+ bool l = furi_hal_gpio_read(&gpio_cc1101_g0);
|
|
|
+ if (l != last_level) break;
|
|
|
+ }
|
|
|
+ if (maxloops == 0) {
|
|
|
+ FURI_LOG_E(TAG, "Max loops reached in DS");
|
|
|
+ furi_delay_tick(1);
|
|
|
+ }
|
|
|
+ /* g0 no longer equal to last level. */
|
|
|
+ uint32_t now = DWT->CYCCNT;
|
|
|
+ uint32_t dur = now - last_change_time;
|
|
|
+ dur /= furi_hal_cortex_instructions_per_microsecond();
|
|
|
+ raw_samples_add(RawSamples, last_level, dur);
|
|
|
+ last_level = !last_level; /* What g0 is now. */
|
|
|
+ last_change_time = now;
|
|
|
+ if (j < 10) d[j] = dur;
|
|
|
+ if (!app->txrx->ds_thread_running) break;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (uint32_t j = 0; j < 10; j++) {
|
|
|
+ FURI_LOG_E(TAG, "dur[%u]: %u",
|
|
|
+ (unsigned int)j, (unsigned int)d[j]);
|
|
|
+ }
|
|
|
+ furi_delay_tick(200);
|
|
|
+ }
|
|
|
+ FURI_LOG_E(TAG, "Exiting DS thread");
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void raw_sampling_worker_start(ProtoViewApp *app) {
|
|
|
+ if (app->txrx->ds_thread != NULL) return;
|
|
|
+ app->txrx->ds_thread_running = true;
|
|
|
+ app->txrx->ds_thread = furi_thread_alloc_ex("ProtoView DS", 2048, direct_sampling_thread, app);
|
|
|
+ furi_thread_start(app->txrx->ds_thread);
|
|
|
+}
|
|
|
+
|
|
|
+void raw_sampling_worker_stop(ProtoViewApp *app) {
|
|
|
+ if (app->txrx->ds_thread == NULL) return;
|
|
|
+ app->txrx->ds_thread_running = false;
|
|
|
+ furi_thread_join(app->txrx->ds_thread);
|
|
|
+ furi_thread_free(app->txrx->ds_thread);
|
|
|
+ app->txrx->ds_thread = NULL;
|
|
|
+}
|