22#include "em_cmu.h"
33#include "em_gpio.h"
44
5+ #include "sl_sleeptimer.h"
56#include "sl_udelay.h"
67
78#include <joybus/joybus.h>
89#include <joybus/backend/gecko.h>
910
10- #define JOYBUS_DATA_PORT gpioPortD
11- #define JOYBUS_DATA_PIN 3
12- #define JOYBUS_TIMER TIMER0
13- #define JOYBUS_USART USART0
11+ #define JOYBUS_PORT gpioPortD
12+ #define JOYBUS_PIN 3
13+ #define JOYBUS_TIMER TIMER0
14+ #define JOYBUS_USART USART0
1415
15- #define LED_PORT gpioPortA
16- #define LED_PIN 4
16+ #define LED_PORT gpioPortA
17+ #define LED_PIN 4
1718
19+ #define JOYBUS_POLL_INTERVAL_MS 15
20+
21+ // Joybus instance
1822struct joybus_gecko gecko_bus ;
1923struct joybus * bus = JOYBUS (& gecko_bus );
2024
21- static uint8_t response [JOYBUS_BLOCK_SIZE ] = {0 };
25+ // Buffer for Joybus responses
26+ static uint8_t joybus_response [JOYBUS_BLOCK_SIZE ] = {0 };
2227
23- static uint16_t last_buttons = 0 ;
24- static uint16_t down_buttons = 0 ;
25- static uint16_t up_buttons = 0 ;
28+ // Polling mode
29+ enum { POLL_MODE_IDENTIFY , POLL_MODE_READ } ;
30+ static uint8_t poll_mode = POLL_MODE_IDENTIFY ;
2631
27- static void identify_cb (struct joybus * bus , int result , void * user_data )
32+ void joybus_identify_cb (struct joybus * bus , int result , void * user_data )
2833{
34+ // Stay in identify mode on any Joybus error
35+ if (result < 0 )
36+ return ;
37+
38+ // Check it's a GameCube controller
39+ uint16_t type = joybus_id_get_type (joybus_response );
40+ if (!(type & JOYBUS_ID_GCN_DEVICE ))
41+ return ;
42+
43+ // Check we've received data if it's a wireless controller
44+ if ((type & JOYBUS_ID_GCN_WIRELESS ) && !(type & JOYBUS_ID_GCN_WIRELESS_RECEIVED ))
45+ return ;
46+
47+ // Check it's a standard controller
48+ if (!(type & JOYBUS_ID_GCN_STANDARD ))
49+ return ;
50+
51+ // Move to polling for input
52+ poll_mode = POLL_MODE_READ ;
2953}
3054
31- static void read_cb (struct joybus * bus , int result , void * user_data )
55+ void joybus_read_cb (struct joybus * bus , int result , void * user_data )
3256{
33- uint16_t buttons = ((response [1 ] << 8 ) | response [0 ]) & JOYBUS_GCN_BUTTON_MASK ;
57+ // Switch back to identify mode on any Joybus error
58+ if (result < 0 ) {
59+ poll_mode = POLL_MODE_IDENTIFY ;
60+ return ;
61+ }
3462
35- down_buttons = ( buttons ^ last_buttons ) & buttons ;
36- up_buttons = (buttons ^ last_buttons ) & last_buttons ;
63+ // Extract button states
64+ uint16_t buttons = (( joybus_response [ 1 ] << 8 ) | joybus_response [ 0 ]) & JOYBUS_GCN_BUTTON_MASK ;
3765
38- last_buttons = buttons ;
66+ // Light the LED while the A button is held
67+ if (buttons & JOYBUS_GCN_BUTTON_A ) {
68+ GPIO_PinOutSet (LED_PORT , LED_PIN );
69+ } else {
70+ GPIO_PinOutClear (LED_PORT , LED_PIN );
71+ }
3972}
4073
74+ // Initialize system clocks
4175static void clock_init ()
4276{
4377 // HFXO initialization
@@ -57,6 +91,20 @@ static void clock_init()
5791 CMU_ClockSelectSet (cmuClock_EM01GRPACLK , cmuSelect_HFXO );
5892}
5993
94+ // Poll Joybus for data
95+ static void poll_task (sl_sleeptimer_timer_handle_t * handle , void * data )
96+ {
97+ switch (poll_mode ) {
98+ case POLL_MODE_IDENTIFY :
99+ joybus_identify (bus , joybus_response , joybus_identify_cb , NULL );
100+ break ;
101+
102+ case POLL_MODE_READ :
103+ joybus_gcn_read (bus , JOYBUS_GCN_ANALOG_MODE_3 , JOYBUS_GCN_MOTOR_STOP , joybus_response , joybus_read_cb , NULL );
104+ break ;
105+ }
106+ }
107+
60108int main ()
61109{
62110 // Initialize chip and clocks
@@ -67,27 +115,19 @@ int main()
67115 CMU_ClockEnable (cmuClock_GPIO , true);
68116 GPIO_PinModeSet (LED_PORT , LED_PIN , gpioModePushPull , 0 );
69117
70- // Initialize and enable the Joybus
71- joybus_gecko_init (& gecko_bus , JOYBUS_DATA_PORT , JOYBUS_DATA_PIN , JOYBUS_TIMER , JOYBUS_USART );
118+ // Initialize Joybus
119+ joybus_gecko_init (& gecko_bus , JOYBUS_PORT , JOYBUS_PIN , JOYBUS_TIMER , JOYBUS_USART );
72120 joybus_enable (bus );
73- sl_udelay_wait (100000 );
74-
75- // Ask any connected target for their ID
76- joybus_identify (bus , response , identify_cb , NULL );
77- sl_udelay_wait (100000 );
78121
79- while (1 ) {
80- // Read the controller state
81- joybus_gcn_read (bus , JOYBUS_GCN_ANALOG_MODE_3 , JOYBUS_GCN_MOTOR_STOP , response , read_cb , NULL );
122+ // Poll for Joybus data at regular intervals
123+ sl_sleeptimer_timer_handle_t poll_timer ;
124+ sl_sleeptimer_init ();
125+ sl_sleeptimer_start_periodic_timer (& poll_timer , sl_sleeptimer_ms_to_tick (JOYBUS_POLL_INTERVAL_MS ), poll_task , bus , 0 ,
126+ SL_SLEEPTIMER_NO_HIGH_PRECISION_HF_CLOCKS_REQUIRED_FLAG );
82127
83- // Toggle LED on PA4 based on A button state
84- if (last_buttons & JOYBUS_GCN_BUTTON_A ) {
85- GPIO_PinOutSet (LED_PORT , LED_PIN );
86- } else {
87- GPIO_PinOutClear (LED_PORT , LED_PIN );
88- }
128+ // No work to do in main loop
129+ while (true)
130+ ;
89131
90- // Wait a bit before reading again
91- sl_udelay_wait (10000 );
92- }
132+ return 0 ;
93133}
0 commit comments