Sfoglia il codice sorgente

new file: adc_driver.hpp

yoneda 1 anno fa
parent
commit
ce31ba37a1
3 ha cambiato i file con 125 aggiunte e 1 eliminazioni
  1. 3 0
      CMakeLists.txt
  2. 104 0
      adc_driver.hpp
  3. 18 1
      main.cpp

+ 3 - 0
CMakeLists.txt

@@ -10,7 +10,9 @@ project(ADRS2040U_i2c)
 pico_sdk_init()
 
 add_executable(${PROJECT_NAME}
+	ADRS2040U_i2c.h
 	main.cpp
+	adc_driver.hpp
 )
 
 # Add pico_stdlib library which aggregates commonly used features
@@ -20,6 +22,7 @@ target_link_libraries(${PROJECT_NAME}
 	pico_i2c_slave
 	hardware_spi
 	hardware_adc
+	hardware_irq
 	pico_multicore
 )
 

+ 104 - 0
adc_driver.hpp

@@ -0,0 +1,104 @@
+#include "hardware/adc.h"
+#include "hardware/irq.h"
+#include "pico/multicore.h"
+#include "hardware/clocks.h"
+
+#include "adrs2040U_i2c.h"
+
+#define ADC_BUFF_SIZE   0x100
+
+auto_init_mutex(adcbuff_mutex);
+
+static volatile int read_p;
+static volatile int write_p;
+static volatile uint16_t adc_buffer[ADC_BUFF_SIZE];
+
+static void adc_interrupt(void)
+{
+    while(! adc_fifo_is_empty()) {
+        mutex_enter_blocking(&adcbuff_mutex);
+        adc_buffer[write_p] = adc_fifo_get() & 0xFFF;
+        write_p = (write_p + 1) & (ADC_BUFF_SIZE - 1);
+        mutex_exit(&adcbuff_mutex);
+    }
+};
+
+class ADC_Driver {
+    private:
+
+        int sample_rate = 1000;
+        uint32_t adc_clk;
+
+        uint8_t adc_pin;
+        uint8_t adc_channel;
+
+    public:
+        ADC_Driver(uint8_t p = 26, uint8_t c = 0) : adc_pin(p),  adc_channel(c) 
+        {
+            read_p = write_p = 0;
+            sample_rate = 1000;
+            adc_init();
+            adc_gpio_init(adc_pin);
+            adc_select_input(adc_channel);
+            adc_fifo_setup(true, false, 1, true, false);
+            // ADCサンプリングクロック設定
+            adc_clk = clock_get_hz(clk_adc);
+            adc_set_clkdiv(adc_clk/sample_rate);
+            // ADC割り込み
+	        irq_set_exclusive_handler(ADC_IRQ_FIFO, adc_interrupt);
+	        irq_set_enabled(ADC_IRQ_FIFO, true);
+            run(false);
+        };
+
+
+        int get_sample_rate(void)
+        {
+            return sample_rate;
+        };
+
+        void set_sample_rate(int rate)
+        {
+            sample_rate = rate;
+            adc_set_clkdiv(adc_clk/sample_rate);
+        };
+
+        bool is_empty(void)
+        {
+            return (read_p == write_p);
+        };
+
+        int get_value(void)
+        {
+            int wp;
+            int rv;
+
+            mutex_enter_blocking(&adcbuff_mutex);
+            wp = write_p;
+            mutex_exit(&adcbuff_mutex);
+            if(read_p != wp) {
+                rv = adc_buffer[read_p];
+                read_p = (read_p + 1) & (ADC_BUFF_SIZE - 1);
+            }
+            else
+                rv = -1;
+
+            return rv;
+        };
+
+        uint8_t count(void)
+        {
+            uint8_t r;
+            mutex_enter_blocking(&adcbuff_mutex);
+            r = write_p - read_p;
+            mutex_exit(&adcbuff_mutex);
+
+            return r;
+        }
+
+        void run(bool r)
+        {
+            adc_irq_set_enabled(r);
+            adc_run(r);
+        };
+
+};

+ 18 - 1
main.cpp

@@ -11,17 +11,34 @@
 #include "hardware/clocks.h"
 
 #include "ADRS2040U_i2c.h"
+#include "adc_driver.hpp"
+
+ADC_Driver adcd;
 
 static void i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event)
 {
+    static uint8_t ADRS2040U_cmd = ADRS2040_CMD_INVALID;
+    uint8_t raw_data;
+
     switch(event) {
         case I2C_SLAVE_RECEIVE:
+            raw_data = i2c_read_byte_raw(i2c);
+            if(ADRS2040U_cmd == ADRS2040_CMD_INVALID) {
+                ADRS2040U_cmd = raw_data;
+            }
             break;
-        
+            
         case I2C_SLAVE_REQUEST:
+            DEBUG_PRINT("I2C_SLAVE_REQUEST\n");
+            if(ADRS2040U_cmd == ADRS2040_CMD_GET_COUNT) {
+                i2c_write_byte_raw(i2c,adcd.count());
+            }
+            else
+                i2c_write_byte_raw(i2c, 0);
             break;
 
         case I2C_SLAVE_FINISH:
+            ADRS2040U_cmd = ADRS2040_CMD_INVALID;
             break;
         
         default: