Advertisement
Guest User

Arduino ADC

a guest
Dec 18th, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.83 KB | None | 0 0
  1. #include <linux/kernel.h>
  2. #include <linux/module.h>
  3. #include <linux/i2c.h>
  4. #include <linux/iio/iio.h>
  5. #include <linux/iio/sysfs.h>
  6. #include <linux/iio/buffer.h>
  7. #include <linux/iio/trigger.h>
  8. #include <linux/iio/trigger_consumer.h>
  9. #include <linux/iio/triggered_buffer.h>
  10. #include <linux/gpio.h>
  11. #include <linux/interrupt.h>
  12.  
  13. #define SCALE 4882
  14. #define IRQ_TRIGGER_PIN 27
  15. static unsigned int irq_trigger;
  16.  
  17. struct arduino_adc_data {
  18.     struct i2c_client *client;
  19.     struct mutex lock;
  20.     struct iio_trigger *trigger;
  21. };
  22.  
  23. static const struct iio_chan_spec arduino_adc_channels[] = {
  24.     {
  25.         .type = IIO_VOLTAGE,
  26.         .indexed = 1,
  27.         .channel = 0,
  28.         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  29.         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
  30.         .scan_index = 0,
  31.         .scan_type = {
  32.             .sign = 's',
  33.             .realbits = 16,
  34.             .storagebits = 16,
  35.             .shift = 0,
  36.             .endianness = IIO_CPU,
  37.         },
  38.     },
  39.     {
  40.         .type = IIO_VOLTAGE,
  41.         .indexed = 1,
  42.         .channel = 1,
  43.         .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
  44.         .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
  45.         .scan_index = 1,
  46.         .scan_type = {
  47.             .sign = 's',
  48.             .realbits = 16,
  49.             .storagebits = 16,
  50.             .shift = 0,
  51.             .endianness = IIO_CPU,
  52.         },
  53.     },
  54. };
  55.  
  56. static const struct iio_trigger_ops arduino_adc_trigger_ops = {
  57.     .owner = THIS_MODULE,
  58. };
  59.  
  60. static irqreturn_t arduino_adc_trigger_handler(int irq, void *p)
  61. {
  62.     int ret;
  63.     struct iio_poll_func *pf = p;
  64.     struct iio_dev *indio_dev = pf->indio_dev;
  65.     struct arduino_adc_data *data = iio_priv(indio_dev);
  66.     __be16 raw[2];
  67.     int to_buffer[2];
  68.  
  69.     ret = i2c_master_recv(data->client, (char *)&raw, 4);
  70.     if (ret < 0)
  71.         return ret;
  72.  
  73.     to_buffer[0] = raw[0];
  74.     to_buffer[1] = raw[1];
  75.  
  76.     iio_push_to_buffers_with_timestamp(indio_dev, to_buffer,
  77.         pf->timestamp);
  78.  
  79.     iio_trigger_notify_done(indio_dev->trig);
  80.  
  81.     return IRQ_HANDLED;
  82. }
  83.  
  84. static irqreturn_t erpi_gpio_irq_handler(unsigned int irq, void
  85.                                          *dev_id, struct pt_regs *regs)
  86. {
  87.     return IRQ_HANDLED;
  88. }
  89.  
  90. static int arduino_adc_read(struct arduino_adc_data *data, int *val, int channel)
  91. {
  92.     int ret;
  93.     __be16 result[2];
  94.  
  95.     if(channel & ~1) {
  96.         return -EINVAL;
  97.     }
  98.  
  99.     ret = i2c_master_recv(data->client, (char *)&result, 4);
  100.     if (ret < 0)
  101.         return ret;
  102.  
  103.     *val = be16_to_cpu(result[channel]);
  104.  
  105.     return 0;
  106. }
  107.  
  108. static int arduino_adc_read_raw(struct iio_dev *indio_dev,
  109.                struct iio_chan_spec const *chan,
  110.                int *val, int *val2, long mask)
  111. {
  112.     int ret;
  113.     struct arduino_adc_data *data = iio_priv(indio_dev);
  114.  
  115.     switch (mask) {
  116.     case IIO_CHAN_INFO_RAW:
  117.  
  118.         if (iio_buffer_enabled(indio_dev)) {
  119.             return -EBUSY;
  120.         }
  121.        
  122.         switch (chan->type) {
  123.         case IIO_VOLTAGE:
  124.             mutex_lock(&data->lock);
  125.             ret = arduino_adc_read(data, val, chan->channel);
  126.             mutex_unlock(&data->lock);
  127.             if (ret < 0)
  128.                 return ret;
  129.  
  130.             return IIO_VAL_INT;
  131.         default:
  132.             return -EINVAL;
  133.         }
  134.     case IIO_CHAN_INFO_SCALE:
  135.         *val = SCALE / 1000000;
  136.         *val2 = SCALE % 1000000;
  137.         return IIO_VAL_INT_PLUS_MICRO;
  138.     default:
  139.         return -EINVAL;
  140.     }
  141. }
  142.  
  143. static int arduino_adc_write_raw(struct iio_dev *indio_dev,
  144.                 struct iio_chan_spec const *chan,
  145.                 int val, int val2, long mask)
  146. {
  147.     return 0;
  148. }
  149.  
  150. static const struct iio_info arduino_adc_info = {
  151.     .read_raw = arduino_adc_read_raw,
  152.     .write_raw = arduino_adc_write_raw,
  153. };
  154.  
  155. static int arduino_adc_probe(struct i2c_client *client,
  156.             const struct i2c_device_id *id)
  157. {
  158.     int ret;
  159.     struct arduino_adc_data *data;
  160.     struct iio_dev *indio_dev;
  161.  
  162.     printk(KERN_INFO "arduino_adc_probe called.\n");
  163.  
  164.     indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
  165.     if (!indio_dev)
  166.         return -ENOMEM;
  167.  
  168.     data = iio_priv(indio_dev);
  169.     i2c_set_clientdata(client, indio_dev);
  170.     data->client = client;
  171.  
  172.     indio_dev->dev.parent = &client->dev;
  173.     indio_dev->info = &arduino_adc_info;
  174.     indio_dev->name = id->name;
  175.     indio_dev->channels = arduino_adc_channels;
  176.     indio_dev->num_channels = ARRAY_SIZE(arduino_adc_channels);
  177.     indio_dev->modes = INDIO_DIRECT_MODE;
  178.  
  179.     gpio_request(IRQ_TRIGGER_PIN, "sysfs");
  180.     gpio_direction_input(IRQ_TRIGGER_PIN);
  181.     gpio_export(IRQ_TRIGGER_PIN, false);
  182.     irq_trigger = gpio_to_irq(IRQ_TRIGGER_PIN);
  183.  
  184.     ret = request_irq(irq_trigger,
  185.                 (irq_handler_t) erpi_gpio_irq_handler,
  186.                 IRQF_TRIGGER_RISING,
  187.                 "rpi_gpio",
  188.                 indio_dev);
  189.     if (ret < 0) {
  190.         return ret;
  191.     }
  192.  
  193.     data->trigger = devm_iio_trigger_alloc(&client->dev, "rpi_gpio");
  194.     if(!data->trigger){
  195.         return -ENOMEM;
  196.     }
  197.     data->trigger->dev.parent = &client->dev;
  198.     data->trigger->ops = &arduino_adc_trigger_ops;
  199.     iio_trigger_set_drvdata(data->trigger, indio_dev);
  200.     indio_dev->trig = data->trigger;
  201.     iio_trigger_get(indio_dev->trig);
  202.     ret = iio_trigger_register(data->trigger);
  203.     if (ret < 0) {
  204.         return ret;
  205.     }
  206.  
  207.     ret = iio_triggered_buffer_setup(indio_dev, NULL,
  208.                      arduino_adc_trigger_handler, NULL);
  209.     if (ret < 0) {
  210.         return ret;
  211.     }
  212.  
  213.     return iio_device_register(indio_dev);
  214. }
  215.  
  216. static int arduino_adc_remove(struct i2c_client *client)
  217. {
  218.     struct iio_dev *indio_dev = i2c_get_clientdata(client);;
  219.     struct arduino_adc_data *data;
  220.     data = iio_priv(indio_dev);
  221.  
  222.     iio_device_unregister(indio_dev);
  223.  
  224.     iio_triggered_buffer_cleanup(indio_dev);
  225.     iio_trigger_unregister(data->trigger);
  226.  
  227.     free_irq(irq_trigger, NULL);
  228.     gpio_unexport(IRQ_TRIGGER_PIN);
  229.     gpio_free(IRQ_TRIGGER_PIN);
  230.  
  231.     return 0;
  232. }
  233.  
  234.  
  235. static const struct i2c_device_id arduino_adc_id[] = {
  236.     { "arduino_adc", 0 },
  237.     { }
  238. };
  239. MODULE_DEVICE_TABLE(i2c, arduino_adc_id);
  240.  
  241. static struct i2c_driver arduino_adc_driver = {
  242.     .driver = {
  243.         .name = "arduino_adc",
  244.     },
  245.     .probe = arduino_adc_probe,
  246.     .remove = arduino_adc_remove,
  247.     .id_table = arduino_adc_id,
  248. };
  249. module_i2c_driver(arduino_adc_driver);
  250.  
  251. MODULE_AUTHOR("Hazael dos Santos Batista");
  252. MODULE_DESCRIPTION("Arduino ADC test driver");
  253. MODULE_LICENSE("GPL");
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement