As part of my audio project https://community.milkv.io/t/cv1800b-audio-project/3534 I’ve been working with the ADC on the CV1800B SoC. The kernel driver for the ADC is available in both the V1 and V2 SDKs and there’s a nice example available as well so I was able to get it running and learned a few things:
- The existing kernel driver is incomplete - it has interfaces for both the usual char device in the /dev directory and a sysfs entry, but the char device read() function will not work as it doesn’t pass its value back to the caller’s buffer. The sysfs show() function on the other hand returns its value as an ASCII string with a decimal numeric value which is easy to read when you just ‘cat’ the file from the command line but requires you to convert it back to an integer so it’s a bit cumbersome to use within a program.
- The read() and show() functions are similar in that they trigger a conversion and then wait while the ADC is busy before reading the result and returning it. The problem here is that they busywait inside a spinlock_irqsave() so the entire kernel is blocked for 20us while waiting for the conversion. This may be OK if you’re only doing conversions occasionally, but it can seriously hamper performance if conversions are requested frequently.
Because of these issues, I’ve modified the driver to get the read() operation to return a binary value and also digging deeper into how to avoid hogging the system during conversions. There is an IRQ available for the end-of-conversion and there may be a way to use that. I’ve also added some logic to control an external analog MUX via GPIO to get more input channels and this is working well.
The hardware aspect of the ADC seems fine - the datasheet doesn’t go into much detail how it works, but from the register map I’ve been able to infer a lot of the details and it seems sane. Overall performance of the converter isn’t great - I see a fair amount of sample-to-sample noise with a standard deviation of about 5 lsbs near max input range but I suppose that’s to be expected on a complex SoC like this. With a bit of post-processing in software it will be usable.
Modified driver here: https://github.com/emeb/duo-buildroot-sdk-v2/blob/audio_board/osdrv/interdrv/saradc/cv180x/cvi_saradc.c
Analysis code here: duo-examples/dev_adc at main · emeb/duo-examples · GitHub