I want to use Socket 9 pins 3 & 4 as GPIO, and 5 for Analog reading.
Is this correct?
Pin 3 = GPIO 46
Pin 4 = GPIO 6
For analog input:
Pin 5 = AD 3
I was able to use these pins just fine in managed code. But in my ported code, it doesn’t seem to be returning any values – generalArray is full of 0.
So I simplified my code to the most basic to just read the analog values. I’m feeding the analog pin the output from my iPhone - P5 to the tip and GND to the sleeve. I’m still getting just 0s.
To ensure that data is being passed between managed & RLP, I changed assignment to: generalArray[i] = i; and in managed, it’s showing 0 thru 7.
int GHAL_AnalogIn_Read(unsigned char channel)
{
return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) >> 8) & 0x3FF;
}
int GetReadings(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
int i;
for (i = 0; i < 7; i++)
{
RLPext->Delay(10);
// read the analog value
generalArray[i] = GHAL_AnalogIn_Read(3);
}
return 0;
}
In managed:
var intArray = new int[7];
var result = GetReadings.InvokeEx(intArray);
// C#: Foo7.InvokeEx(intArray, byteArray); // uses a generalArray (intArray) // one variable argument (byteArray)
int Foo7(int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
// argsCount == 1
// argSize[0] == 10
unsigned char *byteArray = (unsigned char*)args[0]; // same byteArray in C#
// generalArray is the same as intArray in C#
return 0; // Some return value
}
int *intArray = (int*)args[0];
int i;
for (i = 0; i < 7; i++)
{
RLPext->Delay(10);
// read the analog value
intArray[i] = GHAL_AnalogIn_Read(3);
}
return 0;
Still gives zeros. If I change the managed to:
var result = GetReadings.Invoke(intArray);
I get an exception “Argument (0) is not supported”
You need to configure the PIN for AD input, configure the AD clock, and many more
Then you need to start AD conversion and wait for ADC_DONE flag before each read.
DWORD ADCInit( DWORD ADC_Clk )
{
/* Enable CLOCK into ADC controller */
PCONP |= (1 << 12);
/* all the related pins are set to ADC inputs, AD0.0~7 */
PINSEL0 |= 0x0F000000; /* P0.12~13, A0.6~7, function 11 */
PINSEL1 &= ~0x003FC000; /* P0.23~26, A0.0~3, function 01 */
PINSEL1 |= 0x00154000;
PINSEL3 |= 0xF0000000; /* P1.30~31, A0.4~5, function 11 */
AD0CR = ( 0x01 << 0 ) | /* SEL=1,select channel 0~7 on ADC0 */
( ( Fpclk / ADC_Clk - 1 ) << 8 ) | /* CLKDIV = Fpclk / 1000000 - 1 */
( 0 << 16 ) | /* BURST = 0, no BURST, software controlled */
( 0 << 17 ) | /* CLKS = 0, 11 clocks/10 bits */
( 1 << 21 ) | /* PDN = 1, normal operation */
( 0 << 22 ) | /* TEST1:0 = 00 */
( 0 << 24 ) | /* START = 0 A/D conversion stops */
( 0 << 27 ); /* EDGE = 0 (CAP/MAT singal falling,trigger A/D conversion) */
return (TRUE);
}
DWORD ADC0Read( BYTE channelNum )
{
#if !ADC_INTERRUPT_FLAG
DWORD regVal, ADC_Data;
#endif
/* channel number is 0 through 7 */
if ( channelNum >= ADC_NUM )
{
channelNum = 0; /* reset channel number to 0 */
}
AD0CR &= 0xFFFFFF00;
AD0CR |= (1 << 24) | (1 << channelNum);
/* switch channel,start A/D convert */
while ( 1 ) /* wait until end of A/D convert */
{
regVal = *(volatile unsigned long *)(AD0_BASE_ADDR
+ ADC_OFFSET + ADC_INDEX * channelNum);
/* read result of A/D conversion */
if ( regVal & ADC_DONE )
{
break;
}
}
AD0CR &= 0xF8FFFFFF; /* stop ADC now */
if ( regVal & ADC_OVERRUN ) /* save data when it's not overrun, otherwise, return zero */
{
return ( 0 );
}
ADC_Data = ( regVal >> 6 ) & 0x3FF;
return ( ADC_Data ); /* return A/D conversion value */
}
EDIT: Ooops, I just see that the example creates a managed AnalogIn object which should do the initialization for you, so make sure you also create a managed AnalogIn object.
Also, an Analog reading, I thought, was between 0 and 3.3V. How is this converted to a byte? Is it just 0 thru 33?
**
With your and others assistance, I feel like I am getting close to getting it to work – not really fully understanding it, but chipping a bit off the top of the iceberg
Right shift with 8 is the same as dividing by 256. In essence, this means that the value starts at bit 9, so you shift away the lower 8 bits. Next is a mask of 0x3ff, that only keeps the lower 10 bits.
So the RLP version is working (sorta), but is is getting a lot of “phantom” readings.
I have an WPF app that generates the different tones my chip will read back the levels to me - using the analog in. My computer is connected to the device via head phone jack, so you won’t hear anything in the video. I’m turning on the 4th frequency in the various videos.
This is the managed version of the code.
This is the RLP version. You can see the bar is indicating the frequency being generated, but the other bars are providing a bunch of phantom reading.
And here are the values coming back from RLP to managed. At this time, the audio is off. You can see the values are all over the place.
Within the managed version I construct me AnalogIn like this:
InputPin = new GTI.AnalogInput(sock, GT.Socket.Pin.Five, null);
In the managed code, using the RLP for reading, I use this instead (using the Gadgeteer version results in nothing Zeros in the array):
Ok - ill give it a try later on. In the second video, you could see that it seemed that it was reacting to the frequency, so I assumed it was the correct.
Do you suggest that I try all 7 ADC channels? Or is there a way to see which ADC I’m using? According to the GHI datasheet, Socket 9, Pin 5 is AD3.
// You might need to change this depending on the location of the header file
#include <RLP.h>
#define RLP_ADDRESS 0xA0F00000
#define RLP_SIZE 0x000FFFFC
#define ADC_DATA_BASE_ADDRESS 0xE0034010
#define LCD_BASE_ADDR 0xFFE10000
#define LCD_UPBASE (*(volatile unsigned long *)(LCD_BASE_ADDR + 0x0010)) // this define reads out the value from the LCD_UPBASE address
int ResetPin;
int StrobePin;
unsigned short * pixelMap;
// set pins
int Init(unsigned int *generalArray, void **args, unsigned int argsCount,
unsigned int *argSize)
{
ResetPin = 46; // Socket 9 Pin 3
StrobePin = 6; // Socket 9 Pin 4
// config the GPIO pins
RLPext->GPIO.EnableOutputMode(ResetPin, RLP_GPIO_RESISTOR_DISABLED);
RLPext->GPIO.WritePin(ResetPin, RLP_FALSE);
RLPext->GPIO.EnableOutputMode(StrobePin, RLP_GPIO_RESISTOR_DISABLED);
RLPext->GPIO.WritePin(StrobePin, RLP_TRUE);
pixelMap = (unsigned short *)LCD_UPBASE;
// init the chip
RLPext->GPIO.WritePin(ResetPin, RLP_TRUE);
RLPext->Delay(5);
RLPext->GPIO.WritePin(ResetPin, RLP_FALSE);
return 0;
}
int GHAL_AnalogIn_Read(unsigned char channel)
{
return ((*((int*)(ADC_DATA_BASE_ADDRESS) + channel)) ) & 0x3FF; // get 10-bit value; 0-1023
}
int ReadAudio(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argSize)
{
int i=0;
for (i =0; i< 7; i++)
{
// prep for read
RLPext->GPIO.WritePin(StrobePin, RLP_FALSE);
// allow to settle
RLPext->Delay(30);
// read the analog value
generalArray[i] = GHAL_AnalogIn_Read(3);
// set the pin for the next frequency
RLPext->GPIO.WritePin(StrobePin, RLP_TRUE);
}
return 0;
}
Managed code:
int[] dataRPLWave = new int[7];
while (true)
{
Thread.Sleep(50);
ReadAudio.InvokeEx(dataRPLWave, (byte)3);
for (int i = 0; i < 7; i++)
{
if (dataRPLWave[i] > 0 && dataRPLWave[i] < max)
movingAvergage[i].AddValue((int)((dataRPLWave[i] / max) * max));
else
movingAvergage[i].AddValue(0);
}
eq.UpateDisplay(false, false);
}