99#include <stdint.h>
1010#include <string.h>
1111
12- #include <contiki.h>
13-
1412#include <pbdrv/adc.h>
1513#include <pbdrv/clock.h>
1614#include <pbdrv/gpio.h>
1715
1816#include <pbio/error.h>
17+ #include <pbio/os.h>
1918#include <pbio/util.h>
2019
2120#include <tiam1808/spi.h>
2524#include <tiam1808/hw/hw_syscfg0_AM1808.h>
2625#include <tiam1808/armv5/am1808/interrupt.h>
2726
27+ #include "adc_ev3.h"
28+ #include "../drv/block_device/block_device_ev3.h"
2829#include "../drv/gpio/gpio_ev3.h"
2930
30- PROCESS (pbdrv_adc_process , "ADC" );
31+ #include "../sys/storage.h"
32+
33+ #define PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES (2)
3134
32- #define PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES (4)
35+ static volatile uint16_t channel_data [ PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES ];
3336
34- static volatile uint16_t channel_data [PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS + PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES ] = {0 };
35- static volatile uint8_t channel_data_index = 0 ;
36- static volatile bool adc_busy = false;
37+ static int adc_soon ;
38+ // Used to block ADC from interfering with flash upon shutdown
39+ static int shut_down_hack = 0 ;
40+ static int shut_down_hack_done = 0 ;
3741
3842static pbdrv_adc_callback_t pbdrv_adc_callbacks [1 ];
3943static uint32_t pbdrv_adc_callback_count = 0 ;
@@ -48,127 +52,58 @@ pbio_error_t pbdrv_adc_get_ch(uint8_t ch, uint16_t *value) {
4852 if (ch >= PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS ) {
4953 return PBIO_ERROR_INVALID_ARG ;
5054 }
51- // Values for the requested channel are received several samples later.
52- // The data only appears 12-bit but the last 2 bits are always zero.
53- * value = (channel_data [ch + PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES ] - 4096 * ch ) >> 2 ;
55+ // XXX We probably need to figure out how atomicity works between the DMA and the CPU.
56+ // For now, read the value twice and assume it's good (not torn) if the values are the same.
57+ uint16_t a , b ;
58+ do {
59+ // Values for the requested channel are received several samples later.
60+ a = channel_data [ch + PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES ];
61+ b = channel_data [ch + PBDRV_CONFIG_ADC_EV3_NUM_DELAY_SAMPLES ];
62+ } while (a != b );
63+
64+ // Mask the data to 10 bits
65+ * value = (a >> 2 ) & 0x3ff ;
5466 return PBIO_SUCCESS ;
5567}
5668
57- static void spi0_isr (void ) {
58- uint32_t intCode = 0 ;
59- IntSystemStatusClear (SYS_INT_SPINT0 );
60-
61- while ((intCode = SPIInterruptVectorGet (SOC_SPI_0_REGS ))) {
62- if (intCode != SPI_TX_BUF_EMPTY ) {
63- continue ;
64- }
65- // Payload encoding comes from the original EV3 sources, but we
66- // use the hardware SPI peripheral instead of bit-banging.
67- uint16_t payload = 0x1840 | (((channel_data_index % PBDRV_CONFIG_ADC_EV3_ADC_NUM_CHANNELS ) & 0x000F ) << 7 );
68- HWREG (SOC_SPI_0_REGS + SPI_SPIDAT0 ) = payload ;
69- channel_data [channel_data_index ] = SPIDataReceive (SOC_SPI_0_REGS );
70-
71- if (++ channel_data_index == PBIO_ARRAY_SIZE (channel_data )) {
72- SPIIntDisable (SOC_SPI_0_REGS , SPI_TRANSMIT_INT );
73- adc_busy = false;
74- process_poll (& pbdrv_adc_process );
75- }
76- }
77- }
69+ static pbio_os_process_t pbdrv_adc_ev3_process ;
7870
79- static void pbdrv_adc_exit (void ) {
80- SPIIntDisable (SOC_SPI_0_REGS , SPI_RECV_INT | SPI_TRANSMIT_INT );
81- }
71+ pbio_error_t pbdrv_adc_ev3_process_thread (pbio_os_state_t * state , void * context ) {
72+ static pbio_os_timer_t timer ;
8273
83- // ADC / Flash SPI0 data MOSI
84- static const pbdrv_gpio_t pin_spi0_mosi = PBDRV_GPIO_EV3_PIN (3 , 15 , 12 , 8 , 5 );
74+ (void )timer ;
8575
86- // ADC / Flash SPI0 data MISO
87- static const pbdrv_gpio_t pin_spi0_miso = PBDRV_GPIO_EV3_PIN (3 , 11 , 8 , 8 , 6 );
76+ PBIO_OS_ASYNC_BEGIN (state );
8877
89- // LCD SPI0 Clock
90- static const pbdrv_gpio_t pin_spi0_clk = PBDRV_GPIO_EV3_PIN ( 3 , 3 , 0 , 1 , 8 );
78+ // HACK: This waits until storage is completely done with SPI flash before we start
79+ PBIO_OS_AWAIT_UNTIL ( state , pbsys_storage_settings_get_settings () );
9180
92- // ADC / Flash SPI0 chip select (active low) .
93- static const pbdrv_gpio_t pin_spi0_cs = PBDRV_GPIO_EV3_PIN ( 3 , 27 , 24 , 8 , 2 );
81+ // Once SPI flash init is finished, there is nothing further for us to do .
82+ // We are ready to start sampling.
9483
95- // ADCACK PIN
96- static const pbdrv_gpio_t pin_adc_ack = PBDRV_GPIO_EV3_PIN (19 , 19 , 16 , 6 , 2 );
84+ // TODO: Actually start sampling
9785
98- // ADCBATEN
99- static const pbdrv_gpio_t pin_adc_bat_en = PBDRV_GPIO_EV3_PIN ( 1 , 7 , 4 , 0 , 6 );
86+ PBIO_OS_ASYNC_END ( PBIO_SUCCESS );
87+ }
10088
10189void pbdrv_adc_init (void ) {
90+ // Immediately go into async mode so that we can wait for the SPI flash driver.
91+ // We *don't* want to block the initial init phase, or else things will deadlock.
10292
103- // Configure the GPIO pins.
104- pbdrv_gpio_alt (& pin_spi0_mosi , SYSCFG_PINMUX3_PINMUX3_15_12_SPI0_SIMO0 );
105- pbdrv_gpio_alt (& pin_spi0_miso , SYSCFG_PINMUX3_PINMUX3_11_8_SPI0_SOMI0 );
106- pbdrv_gpio_alt (& pin_spi0_clk , SYSCFG_PINMUX3_PINMUX3_3_0_SPI0_CLK );
107- pbdrv_gpio_alt (& pin_spi0_cs , SYSCFG_PINMUX3_PINMUX3_27_24_NSPI0_SCS3 );
108-
109- pbdrv_gpio_input (& pin_adc_ack );
110-
111- pbdrv_gpio_out_high (& pin_adc_bat_en );
112-
113- // Waking up the SPI1 instance.
114- PSCModuleControl (SOC_PSC_1_REGS , HW_PSC_SPI0 , PSC_POWERDOMAIN_ALWAYS_ON , PSC_MDCTL_NEXT_ENABLE );
115-
116- // Register the ISR in the Interrupt Vector Table.
117- IntRegister (SYS_INT_SPINT0 , spi0_isr );
118- IntChannelSet (SYS_INT_SPINT0 , 2 );
119- IntSystemEnable (SYS_INT_SPINT0 );
120-
121- // Reset.
122- SPIReset (SOC_SPI_0_REGS );
123- SPIOutOfReset (SOC_SPI_0_REGS );
124-
125- // Mode.
126- uint32_t spipc0 = SPI_SPIPC0_SOMIFUN | SPI_SPIPC0_SIMOFUN | SPI_SPIPC0_CLKFUN | SPI_SPIPC0_SCS0FUN3 ;
127- SPIModeConfigure (SOC_SPI_0_REGS , SPI_MASTER_MODE );
128- SPIPinControl (SOC_SPI_0_REGS , 0 , 0 , (unsigned int * )& spipc0 );
129-
130- // Config.
131- SPIClkConfigure (SOC_SPI_0_REGS , SOC_SYSCLK_2_FREQ , 2000000 , SPI_DATA_FORMAT0 );
132- SPIConfigClkFormat (SOC_SPI_0_REGS , SPI_CLK_OUTOFPHASE | 0x00000010 , SPI_DATA_FORMAT0 );
133- SPIDelayConfigure (SOC_SPI_0_REGS , 10 , 10 , 10 , 10 );
134- SPIIntLevelSet (SOC_SPI_0_REGS , SPI_RECV_INTLVL | SPI_TRANSMIT_INTLVL );
135- SPIDefaultCSSet (SOC_SPI_0_REGS , 8 );
136-
137- // Enable and loop around all channels.
138- SPIEnable (SOC_SPI_0_REGS );
139-
140- process_start (& pbdrv_adc_process );
93+ pbio_os_process_start (& pbdrv_adc_ev3_process , pbdrv_adc_ev3_process_thread , NULL );
14194}
14295
14396void pbdrv_adc_update_soon (void ) {
144- process_poll (& pbdrv_adc_process );
97+ adc_soon = 1 ;
98+ pbio_os_request_poll ();
14599}
146100
147- PROCESS_THREAD (pbdrv_adc_process , ev , data ) {
148- PROCESS_EXITHANDLER (pbdrv_adc_exit ());
149-
150- static struct etimer etimer ;
151-
152- PROCESS_BEGIN ();
153-
154- etimer_set (& etimer , 10 );
155- for (;;) {
156- PROCESS_WAIT_EVENT_UNTIL ((ev == PROCESS_EVENT_TIMER && etimer_expired (& etimer )) || ev == PROCESS_EVENT_POLL );
157-
158- channel_data_index = 0 ;
159- adc_busy = true;
160- SPIEnable (SOC_SPI_0_REGS );
161- SPIIntEnable (SOC_SPI_0_REGS , SPI_TRANSMIT_INT );
162- PROCESS_WAIT_EVENT_UNTIL (ev == PROCESS_EVENT_POLL && !adc_busy );
163-
164- for (uint32_t i = 0 ; i < pbdrv_adc_callback_count ; i ++ ) {
165- pbdrv_adc_callbacks [i ]();
166- }
167-
168- etimer_reset (& etimer );
169- }
170-
171- PROCESS_END ();
101+ void pbdrv_adc_ev3_shut_down_hack () {
102+ shut_down_hack = 1 ;
103+ pbio_os_request_poll ();
104+ }
105+ int pbdrv_adc_ev3_is_shut_down_hack () {
106+ return shut_down_hack_done ;
172107}
173108
174109#endif // PBDRV_CONFIG_ADC_EV3
0 commit comments