/*既存のsample04と挙動が同じだが * プロセス間制御を適用してイベントキューにタッチイベントをエンキューして、それを定期的にデキューすることで、画面遷移するように改良した。 * */ #include #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" #include "pico/stdlib.h" #include "LCD_driver.h" // 【IPC仕様】プロセス間通信用キュー QueueHandle_t xTouchQueue = NULL; // 【排他仕様】SPIバス保護用セマフォ(Mutexの代わりに使用) SemaphoreHandle_t xDisplaySemaphore = NULL; // --------------------------------------------------------- // Task 1: [P1] スキャナプロセス (20ms周期) // --------------------------------------------------------- void vScanTask(void *pvParameters) { vTaskDelay(pdMS_TO_TICKS(2000)); printf("[T1] P1: Input Scanner Online\n"); int event_signal = 1; bool last_state = false; while (true) { bool current_state = false; // セマフォでバスを確保 if (xDisplaySemaphore != NULL && xSemaphoreTake(xDisplaySemaphore, portMAX_DELAY) == pdTRUE) { current_state = is_touched(); xSemaphoreGive(xDisplaySemaphore); } // 変化点検知 if (current_state && !last_state) { xQueueSend(xTouchQueue, &event_signal, 0); } last_state = current_state; vTaskDelay(pdMS_TO_TICKS(20)); } } // --------------------------------------------------------- // Task 2: [P2]制御 & [P4]TFT描画 (1000ms周期) // --------------------------------------------------------- void vDisplayTask(void *pvParameters) { printf("[T2] Initializing TFT...\n"); LCD_Driver lcd; // 初期化をセマフォで保護 if (xDisplaySemaphore != NULL && xSemaphoreTake(xDisplaySemaphore, portMAX_DELAY) == pdTRUE) { lcd.init(); lcd.drawHSBBackground(); xSemaphoreGive(xDisplaySemaphore); printf("[T2] TFT Initialization Complete\n"); } int total_count = 0; int received_val; printf("[T2] P2&P4: Display Controller Online\n"); while (true) { vTaskDelay(pdMS_TO_TICKS(1000)); bool has_event = false; while (xQueueReceive(xTouchQueue, &received_val, 0) == pdPASS) { total_count++; has_event = true; } if (has_event) { printf("[P2] Control: Event Detected. Total Count = %d\n", total_count); // 描画処理をセマフォで保護 if (xDisplaySemaphore != NULL && xSemaphoreTake(xDisplaySemaphore, portMAX_DELAY) == pdTRUE) { update_hue_on_tap(); lcd.drawHSBBackground(); xSemaphoreGive(xDisplaySemaphore); printf("[P4] TFT Draw Update Done\n"); } } } } // --------------------------------------------------------- // Main // --------------------------------------------------------- int main() { stdio_init_all(); sleep_ms(2000); printf("\n====================================\n"); printf(" IPC Specification: Semaphore Model \n"); printf("====================================\n"); // 【IPC仕様】キュー作成 xTouchQueue = xQueueCreate(100, sizeof(int)); // 【修正】xSemaphoreCreateMutex がエラーになるため、 // バイナリセマフォを作成し、即座に Give して「空き」状態にする xDisplaySemaphore = xSemaphoreCreateBinary(); if (xDisplaySemaphore != NULL) { xSemaphoreGive(xDisplaySemaphore); } if (xTouchQueue != NULL && xDisplaySemaphore != NULL) { xTaskCreate(vDisplayTask, "Display", 4096, NULL, 1, NULL); xTaskCreate(vScanTask, "Scanner", 1024, NULL, 2, NULL); printf("[Main] Starting Scheduler...\n"); vTaskStartScheduler(); } while(1) { tight_loop_contents(); } } // Hooks extern "C" { void vApplicationIdleHook(void) {} void vApplicationTickHook(void) {} void vApplicationMallocFailedHook(void) { printf("[CRITICAL] Malloc Failed!\n"); for(;;); } void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) { printf("[CRITICAL] Stack Overflow in: %s\n", pcTaskName); for(;;); } }