Raspberry Pi with PmodDA2 digital analog conversion - c++

As a part of a project in university, i have to send Data from the Raspberry Pi 2 to the Digilent PmodDA2 using C/C++. For that, i tried to use the bcm2835 library, which can only send 8 bit at a time. The PmodDA2 is a 12 bit device (integer values form 0 to 4095), so how can I transfer alle the bits? In the DACSPI2 Library Reference Manual (functions for Arduino) it even says "this function writes the 12 bits value to the DA converter, by writing 16 bits to SPI..." - so do I have to send 16bits? What do the missing 4 Bits look like then?
What's more, I need information about the clock polarity, the clock phase and if the chip is active at HIGH or at LOW.
Thank's a lot!
PS: For the bit-problem I tried:
char spiOut[3]; char spiIn[3];
if(!bcm2835_init())return 1;
bcm2835_spi_begin();
bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);
bcm2835_spi_setDataMode(BCM2835_SPI_MODE3);
bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_256);
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);
while (k<10) {
spiOut[0]=Data[k] >> 4;//Data[k] contains the Integer values from 0 to 4095
spiOut[1]=((Data[k]&0x00F)<<4)|(Data[k+1]>>8);
spiOut[2]=Data[k+1]&0x0FF;
bcm2835_spi_transfernb(spiOut, spiIn, sizeof(spiOut));

Related

How to write a value to a port in DIO module AUTOSAR?

I am working in an AUTOSAR project on a STM32 NUCLEO-F767ZI board and I have to write the value for a port in the DIO module. I know that there is a function called HAL_GPIO_WritePin(), but how can I make to write the value for an entire port?
You can do that by writing the value for each channel in that port.
The ports usually have 16 channels so the value you want to write is a 16 bit number containing 0 and 1 (LOW and HIGH). So for each bit in that number you call the function HAL_GPIO_WritePin() and use the parameter RESET for 0 and SET for 1 to write the value to the corresponding channel.

Absolute Encoder hexadecimal input

Question: How do I receive input from a absolute encoder that makes it output in hexadecimal/grey code into a Arduino? do I use a digitalRead or analogRead command? I could not find example code/projects with a absolute encoder online.
Overall Objective: I want to use a absolute encoder as a knob for a project. The idea is that the encoder will output its position as a state to be used in a case statement. I.e:
case1: analogRead(absEncdr == 00)
arduino enters idle routine
case2: analogRead(absEncdr == 11)
arduino enters button routine
etc
details: Abs encoder type: 25LB22-G
encoder datasheet is here.
I'm using the hexidecimal/ grey code 4-Bit Binary Code Hexadecimal-16 Position encoder version
Basically, I'm not sure how to read in this abs encoder into my Arduino.
To read that you will need four digital pins. You can read the four pins and bit-shift those values into one byte that you can compare to the table in the data-sheet.
byte position = (digitalRead(pin8) << 3) | (digitalRead(pin4) << 2) | (digitalRead(pin2) << 1) | digitalRead(pin1);
Assuming that the pins are named as they are in that truth table in the datasheet.
We are using the OR operator | to put them together into the same byte.

Why do I get an error when read or write more than 3 bytes using libusb to communicate with a PIC 18F2550?

I'm using libusb in Qt to communicate with a PIC microcontroller, 18F2550. The thing is that it's working OK until I try to send or read more than three bytes. Why does it happen?
I've tried using bulk_read transfer and interrupt_read. When I put the size of the buffer equal or less than three, then the transmission works perfectly, using bulk or interrupt. When this size is greater than three, then I'm getting buffer1 and buffer[2] OK, but the rest are wrong.
The error that I'm getting is from timeout. As input I'm using endpoint 0x81.
More information:
The return value from the bulk or interrupt read is -116. The numbers that I'm sending from the PIC to the PC in the two first bytes ([0] and 1) in hex is 0x02D6. With this number, buffer[0] = -42 (when it should be 0xD6 = 214) and buffer[1] = 2 that is correct.
In the [2] and [3] bytes the number is 0x033D, and I get [2] = 61 = 0x3D. That is correct and [3] = -42??? (like [0]).
And the fifth byte is 1, and the SW shows 2???. Might it be a problem in the microcontroller, because I'm programming it as an HID USB?
I don't think that being a HID is the problem. I had a similar issue before; the PIC would randomly timeout when large data was being transmitted. It turned out to be some voltage fluctuation on the MCU. How are you connecting the crystal? Do you have a capacitor on VUSB to regulate it?
Building a PIC18F USB device is a great tutorial on building a PIC HID, and even though it's not based on 18F2550 but on 18F4550, it should be quite similar, and I'm sure you can get a lot out of the schematics and hardware setup. It was the starting point for my PIC-USB projects.

Problems with endianess on Raspberry Pi

I've just started on some raw network programming in C++ and have been compiling on my Raspberry Pi itself (no cross-compiling). That makes everything little endian.
After constructing my IP header, I calculate the IP checksum, but it was always coming out incorrect (based on an example here http://www.thegeekstuff.com/2012/05/ip-header-checksum/).
Revving up gdb, I've worked my issue down to the ordering of the first 32 bits in the IP header. The example uses 0x4500003C, which means version 4 (0x4), IHL 5 (0x5), TOS 0 (0x00), and tot_length 60 (0x003C). So I set my packet up the same.
struct iphdr* ip; // Also some mallocing
ip->version = 4;
ip->ihl = 5;
ip->tos = 0;
ip->tot_len = 60;
Now in gdb, I examined the first 32 bits, expecting 0x3C000045 because of endianness, but instead I get this:
(gdb) print ip
$1 = (iphdr *) 0x11018
(gdb) x/1xw 0x11018
0x11018: 0x003c0045
The first 16 bits are in little endian (0x0045) but the second, containing decimal 60, seem to be in big endian (0x003C)!
What is giving this? Am I crazy? Am I completely wrong about byte order inside structs? (It's a definite possibility)
There's the order of fields within the struct, and then there's the order of bytes within a multibyte field.
0x003C isn't endian at all, it's the hex value for 60. Sure, it's stored in memory with some endianness, but the order you used to write the field and the order you used to read it back out are the same -- both are the native byte order of the Raspberry Pi, and they cancel out.
Typically you will want to write:
ip->tot_len = htons(60);
when storing a 16-bit field into a packet. There's also htonl for 32-bit fields, and ntohs and ntohl for reading fields from network packets.
The ARM architecture can run both little and big endianess, but the Android platform runs little endian.

How to mix voice audio

I am currently developing a simple VoIP project where multiple clients send out his voice to a server and later the server will mix up those voices together.
However, I can't mix it directly by using simple mathematic addition. Each cycle, a client will send 3584 Bytes voice data to the mixer.
Below is the snippet of the value contained in a receiver buffer:
BYTE buffer[3584];
[0] 0 unsigned char
[1] 192 'À' unsigned char
[2] 176 '°' unsigned char
[3] 61 '=' unsigned char
[4] 0 unsigned char
[5] 80 'P' unsigned char
[6] 172 '¬' unsigned char
[7] 61 '=' unsigned char
[8] 0 unsigned char
[9] 144 '' unsigned char
[10] 183 '·' unsigned char
[11] 61 '=' unsigned char
.
.
.
I'm not so sure how the pattern inside the buffer is generated in that way from a client side but I'm thinking it may be a wave pattern. Now let say I have another similar data like this, how do I mix the voice together.
Please help. Thank you.
You need to find out if your VoIP system uses compression. It probably does, in which case the first thing you need to do is to decompress the streams, then mix them, then recompress.
This is probably an array of floats (unlikely due to the byte pattern presented) or singed integers if it's raw PCM data so try using it as such. Mixing to PCM streams is fairly trivial, just add them together and divide them by two (use other weighting for volume control).
I looked at your data again and they appear to be floating point values the reason I was mistaken in my previous post is probably related to me working on big endian systems for a while now. However your data is in little endian IEEE floating point. Here are the values I got after conversion.
0.089630127 -> 0x0090b73d
0.084136963 -> 0x0050ac3d
0.086303711 -> 0x00c0b03d
As you can see, the values are fairly small so you'll probably need to take that into account when applying the volume; the usual convention is to have this data either between 0..1 or -1..1 for min and max volumes respectively.
Here is part of a mixing loop I've written a few years ago, for reference the full mixer is available here
for(int i = 0; i < a_Sample->count() / a_Sample->channels(); i++){
float l_Volume = a_Sample->volume() * m_MasterVolume;
*l_Output++ += *l_Left * l_PanLeft * l_Volume;
*l_Output++ += *l_Right * l_PanRight * l_Volume;
l_Left += a_Sample->channels();
l_Right += a_Sample->channels();
}
Notice that for the output you'll probably need to convert the data to signed integers so communicate properly if that's the responsibility of the mixer or the outputting device.
As others have mentioned you have to know what format the buffer is in. You can't simply just operate on the bytes directly (well, you could, but it would become quite complicated). Most raw PCM data is usually 44100 bits/second, 16 bit, 2 channel. However, that's not always the case. Each one of those can be different. It won't effect it too much, but is an example. However, even WAV files can be in other formats (like IEEE Float). You will need to interpret the buffer correct as the appropriate data type in order to operate on it.
Like:
BYTE buffer[3584];
if (SampleTypeIsPcm16Bit())
{
short *data = reinterpret_cast<short *>(buffer);
// Rock on
}
else if (SampleTypeIsFloat())
{
float *data = reinterpret_cast<float *>(buffer);
// Rock on
}
Of course, you can make it more generic with templates, but ignore that for know :P.
Keep in mind that if you are dealing with floats, they need to be capped to the range -1.0 and 1.0.
So, are you currently saying the "add two values and divide by two" (mentioned by Jasper) isn't working? How are you playing the data when you just hear silence? I wonder if that's a problem because if your math is off, you would likely hear audio glitches (pops/clicks/etc.) rather than just silence.