Related
I Have a PC Program that is communicating over a TCP/IP Connection to an Embedded board (Infineon XE169 (C166 Family)).
This PC Program request what data is stored on a certain address.
The PC Program is uC/Probe, and I cannot change how this program is working.
uC/Probe for example sends this message:
____________________________________________________________________________________________________________
| Prefix | Length |Pkt_nr|Unused| Format | read size | Address to read |Unused|Postfix|
|--------------------|-----------|------|------|-----------|-----------|----------------------|------|-------|
|0x75 0x43 0x50 0x72 | 0x00 0x08 | 0x00 | 0x00 | 0x02 0x00 | 0x04 0x00 | 0xDC 0x3E 0x61 0x00 | 0x00 | 0x2F |
|u C P r | 8 | 0 | 0 | 2 | 4 | 0x613EDC | 0 | / |
|____________________|___________|______|______|___________|___________|______________________|______|_______|
This is a message to request the data from address 0x613EDC and read 4 bytes from there.
When looking in the .map file I can see that at this location the OSTCBCurPtr variable is placed.
This variable is an OS_TCB* thus at the requested address is the address placed where this variable is pointing to.
I've now manually looked in the .map file what kind of variable is placed on the address. But can I get the variable type trough the C code on the Embedded board. All I want to know is if the object that lies on that specific location is a pointer or not, if it's an uint16_t, uint8_t, char or whatever is unimportant to me.
Background information, why I want to know this
The Embedded board will sent back the requested data to the uC/Probe program. But the pointers are stored in a strange way in the XE169 chip.
The pointer of above example is for example stored like this:
_______________________________________
| Address | 0 | 1 | 2 | 3 |
|-----------|------|------|------|------|
|0x00613EDC | 0xE6 | 0x1F | 0x84 | 0x01 |
|___________|______|______|______|______|
Because the value's are stored little endian this would result in the number
0x01841FE6.
This number is currently send back to uC/Probe. But his number isn't the correct location of the, a little calculation has to be done to get to the actual address location.
We have to take apart this 32bits number and split it into 2 16 bit numbers.
Then we get:
Hex: 0x0184 and 0x1FE6
Bits: 0b0000000110000100 and 0001111111100110
Now the 16 upper bits have to move 2 bits to the right. The 2 least significant bits of these upper 16 bits become the 2 most significant bits on the lower 16 bits.
This results into:
Hex: 0x0061 and 0x1FE6
Bits: 0b0000000001100001 and 0001111111100110
When we paste these 2 16 bit numbers back to the 32 bit number we have the address where the pointer is pointing to:
0x00611FE6
And this is the number I have to sent back to uC/Probe.
This calculation only has to happen for when uC/Probe requests pointers, for non pointers it just needs to send back the data read from the given address.
That's why I need to know if the requested data is a pointer, hopefully someone can help me with this.
I am using MPC 7555 controller. It has a 16 bit sigma delta ADC.
A signal called mic input is fed to this ADC pin. based upon the voltage , a PWM signal of same frequency of ADC signal sampling should be generated.
For e.g.
0.1 V = 2 percent
0.2 V = 4 percent
0.3 V = 6 percent....and so on
So, i thought the following logic -
5V - 0xFFFF in digital
0.1V - 1310
0.2V - 2620 and so on
So, dividing the digital value by 655 will give exact duty cycle value
1310/655 = 2
2620/655 = 4........
But digital pin could also show value of 1309 for 0.1 V which when divided by 655 would yield 1 and not 2.
Anyway i can avoid this or does any have a better solution, please share.
The task is to output PWM at the same rate as the ADC conversion rate.
Suppose the ADC conversion time is T (you can establish this by reading a free-run timer counter). And suppose the ADC conversion value is V. Then the PWM output time H spent "high" must be
H = T * V / 0xFFFF
Every time an ADC conversion is available, you (cancel any pending one-shot timer interrupt and) set the PWM output to 1 and trigger a one-shot timer at time H. When it interrupts, you set the PWM output to 0 (or the other way round if you have inverse logic).
If the input is 0x0000 or 0xFFFF you can employ an alternative strategy - set the output to 0 or 1, but don't deploy the one-shot timer.
To get the best fidelity in teh PWM signal, you would do better to work directly at the resolution of the PWM rather then calculate a percentage only to then convert that to a PWM count. Using integer percentage, you are effectively limiting your resolution to 6.64 bits per sample (i.e. log10(100)/log10(2)).
So let's say your PWM count per cycle is PWM_MAX, and your ADC maximum ADC_MAX, then the PWM high period would be:
pwm_high = adc_val * PWM_MAX / ADC_MAX ;
It is important to perform the multiplication first to avoid loss of information. If PWM_MAX is suficiently high, there is probably no need to worry about integer division rounding toward zero rather then to teh nearest integer, but if that is a concern (for low PWM_MAX ) then:
pwm_high = ((adc_val * PWM_MAX) + (ADC_MAX / 2)) / ADC_MAX ;
For example, soy your PWM_MAX is only 100 (i.e. the resolution truely is in integer percent), then in the first case:
pwm_high = 1310 * 100 / 0xFFFF = 1
and in the second:
pwm_high = ((1310 * 100) + 0x7FFF) / 0xFFFF = 2
However if PWM_MAX is a more suitable 4096 perhaps, then:
pwm_high = 1310 * 4096 / 0xFFFF = 81
or
pwm_high = ((1310 * 4096) + 0x7fff) / 0xFFFF = 82
With PWM_MAX at 4096 you have effectively 12 bits of resolution and will maintain much higher fidelity as well as directly calculating the correct PWM value.
I installed portaudio on Ubuntu 14.04 and compiled a test program as follows:
gcc -o Test3c Test3c.c ../libportaudio.a -lrt -lasound -ljack -lpthread -lm
which had no errors. (Test3c.c is the same as the included pa_devs.c, which can be found here.) But when I run it,
./Test3c
I get this:
ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2239:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
bt_audio_service_open: connect() failed: Connection refused (111)
bt_audio_service_open: connect() failed: Connection refused (111)
bt_audio_service_open: connect() failed: Connection refused (111)
bt_audio_service_open: connect() failed: Connection refused (111)
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
PortAudio version number = 1899
PortAudio version text = 'PortAudio V19-devel (built Feb 14 2015 11:51:22)'
Number of devices = 20
--------------------------------------- device #0
Name = HDA Intel PCH: ALC892 Analog (hw:0,0)
Host API = ALSA
Max inputs = 2, Max outputs = 6
Default low input latency = 0.0058
Default low output latency = 0.0087
Default high input latency = 0.0348
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 2 channel input =
44100.00, 48000.00, 96000.00, 192000.00
Supported standard sample rates
for half-duplex 16 bit 6 channel output =
None
Supported standard sample rates
for full-duplex 16 bit 2 channel input, 6 channel output =
None
--------------------------------------- device #1
Name = HDA Intel PCH: ALC892 Digital (hw:0,1)
Host API = ALSA
Max inputs = 0, Max outputs = 2
Default low input latency = -1.0000
Default low output latency = 0.0058
Default high input latency = -1.0000
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 2 channel output =
32000.00, 44100.00, 48000.00, 88200.00,
96000.00, 192000.00
--------------------------------------- device #2
Name = HDA Intel PCH: ALC892 Alt Analog (hw:0,2)
Host API = ALSA
Max inputs = 2, Max outputs = 0
Default low input latency = 0.0058
Default low output latency = -1.0000
Default high input latency = 0.0348
Default high output latency = -1.0000
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 2 channel input =
44100.00, 48000.00, 96000.00, 192000.00
--------------------------------------- device #3
Name = HDA NVidia: HDMI 0 (hw:1,3)
Host API = ALSA
Max inputs = 0, Max outputs = 8
Default low input latency = -1.0000
Default low output latency = 0.0058
Default high input latency = -1.0000
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 8 channel output =
32000.00, 44100.00, 48000.00, 88200.00,
96000.00, 192000.00
--------------------------------------- device #4
Name = HDA NVidia: HDMI 0 (hw:1,7)
Host API = ALSA
Max inputs = 0, Max outputs = 8
Default low input latency = -1.0000
Default low output latency = 0.0058
Default high input latency = -1.0000
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 8 channel output =
32000.00, 44100.00, 48000.00, 88200.00,
96000.00, 192000.00
--------------------------------------- device #5
Name = HDA NVidia: HDMI 0 (hw:1,8)
Host API = ALSA
Max inputs = 0, Max outputs = 8
Default low input latency = -1.0000
Default low output latency = 0.0058
Default high input latency = -1.0000
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 8 channel output =
32000.00, 44100.00, 48000.00, 88200.00,
96000.00, 192000.00
--------------------------------------- device #6
Name = HDA NVidia: HDMI 0 (hw:1,9)
Host API = ALSA
Max inputs = 0, Max outputs = 8
Default low input latency = -1.0000
Default low output latency = 0.0058
Default high input latency = -1.0000
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 8 channel output =
32000.00, 44100.00, 48000.00, 88200.00,
96000.00, 192000.00
--------------------------------------- device #7
Name = sysdefault
Host API = ALSA
Max inputs = 128, Max outputs = 128
Default low input latency = 0.0213
Default low output latency = 0.0213
Default high input latency = 0.0213
Default high output latency = 0.0213
Default sample rate = 48000.00
Supported standard sample rates
for half-duplex 16 bit 128 channel input =
8000.00, 9600.00, 11025.00, 16000.00,
22050.00, 32000.00, 44100.00, 48000.00,
88200.00
Supported standard sample rates
for half-duplex 16 bit 128 channel output =
8000.00, 9600.00, 11025.00, 16000.00,
22050.00, 32000.00, 44100.00, 48000.00,
88200.00
Supported standard sample rates
for full-duplex 16 bit 128 channel input, 128 channel output =
8000.00, 9600.00, 11025.00, 16000.00,
22050.00, 32000.00, 44100.00, 48000.00,
88200.00
--------------------------------------- device #8
Name = front
Host API = ALSA
Max inputs = 0, Max outputs = 6
Default low input latency = -1.0000
Default low output latency = 0.0058
Default high input latency = -1.0000
Default high output latency = 0.0348
Default sample rate = 44100.00
Supported standard sample rates
for half-duplex 16 bit 6 channel output =
Test3c: pcm_params.c:2249: snd1_pcm_hw_params_slave: Assertion `err >= 0' failed.
Aborted (core dumped)
It crashes midway through listing the devices, when Pa_IsFormatSupported() is called. Google tells me that "pcm_params.c" refers to the ALSA library. Has anyone found a solution to this type of problem?
So I think I've found a solution. After the most recent error, I noticed the recommendation for a different audio issue here to restart the audio drivers in the following way:
pulseaudio -k && sudo alsa force-reload
I did it, and then tried running the compiled program, and got errors again (I think I was being impatient). I then did this command a second time, and now it works.
update: After a while, I do get the error again, and have to restart the drivers again.
Currently I am the maintainer of the Portaudio-linux host, and have just come across this question here. The same issue has been reported on the Portaudio mailing list, and investigated. The assert is in Alsa-lib, and has now been removed by the Alsa-developers in favour of an error return. See
http://git.alsa-project.org/?p=alsa-lib.git;a=commit;h=67f73b0fab466e780dcc0442e19894a1cbedc43b
Certain devices seem to cause a problem with 6-channels on 'front' (and some other) PCMs. This is not a fault of Portaudio, but as it probes the capabilities of the devices and PCMs it exposes issues within the Alsa system. With the assert removed, it now just fails these capabilities.
I encountered the same problem and resolved it by fixing some faulty pcm definitions in /usr/share/alsa/pcm. In the route section towards the bottom of the file the card driver was referencing a different pcm then the one defined in the file.
I am completely new to embedded programming, I'm examining the code below and trying to understand how it work, but I really got stuck.
The program is used to count and print out the numbers from 0 to 9.
So can someone please explain the line const uint8_t ? why do I need an array of heximal number here?
#include <avr/io.h>
#include <util/delay.h>
#include "debug.h"
const uint8_t segments[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE4,0xFE,0xF6};
int main(void) {
uint8_t i=0; //s
int g;
init_debug_uart0();
/* set PORT A pins as outputs */
DDRA = 0xFF;
for (;;) {
PORTA = segments[i];
printf("%d\n\r",i);
_delay_ms(1000);
if (i >=9) {
fprintf(stderr , "Count Overflow\n\r"); i = 0;
scanf("%d", &g);
}else
i++;
}
}
And a final question, does anyone know good sources to read about embedded programming? Currently i'm learning about the IIMatto, 8-bits processor and it has 32-registers, designed in Harvard architecture and has 1 level pipeline.
The const uint8_t segments[10] = {0xFC,0x60,0xDA, ... simple defines a constant 10-byte array of bytes.
Code does not need an array of hexadecimal, it could have been decimal.
But consider the benefit of
0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE4,0xFE,0xF6
// versus
252,96,218,...
A casual inspection shows that the number of bits set in each byte is
6,2,5,5,...
This just happens to match the number of segments set in a 7-segment display of the digits 0,1,2,3 ...
Closer inspection of the bits set will detail which bit activate what segment.
Other methods could be employed to get this mapping of 7-segment to digit, but showing the data in hexadecimal is one step closer than decimal.
Perhaps code could be like (the proper segment mapping is TBD).
typedef enum {
LED7_a = 1 << 0,
LED7_b = 1 << 1,
LED7_c = 1 << 2,
LED7_d = 1 << 3,
LED7_e = 1 << 4,
LED7_f = 1 << 5,
LED7_g = 1 << 6,
LED7_dp = 1 << 7
} LED7_Segment_t;
/* ****************************************************************************
7 Segment Pattern
Layout
aaa
f b
f b
ggg
e c
e c
ddd dp
**************************************************************************** */
const uint8_t segments[] = {
/*'0*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_e | LED7_f ,
/*'1*/ LED7_b | LED7_c ,
/*'2*/ LED7_a | LED7_b | LED7_d | LED7_e | LED7_g,
/*'3*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_g,
/*'4*/ LED7_b | LED7_c | LED7_f | LED7_g,
/*'5*/ LED7_a | LED7_c | LED7_d | LED7_f | LED7_g,
/*'6*/ LED7_a | LED7_c | LED7_d | LED7_e | LED7_f | LED7_g,
/*'7*/ LED7_a | LED7_b | LED7_c ,
/*'8*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_e | LED7_f | LED7_g,
/*'9*/ LED7_a | LED7_b | LED7_c | LED7_d | LED7_f | LED7_g};
First of all, ask yourself where is segments used, what is it used for, how is it used?
Hints:
Where: Used to assign a value to PORTA
What: PORTA Is an output from an embedded system. Perhaps to an external device. segments is used to store outputs.
How: Each time around the loop, the value i is incremented. i is used as the index for segments when its value is assigned to PORTA.
Also: A hexadecimal number, specifically 2 digits long, is a byte which is 8 bits. Look on your microcontroller for up to 8 pins labelled "PORTA"
When writing to PORTA (an I/O port) you are concerned with the state of individual I/O lines associated with each bit.
To display a specific set of segments representing a digit on a 7-segment display, you have to write a specific bit pattern - one bit for each segment you wish to light. The segments array is indexed by the digit you want to display, and the value at that index represents the bit pattern on PORTA required to light the segments that represent that digit.
The reason hexadecimal is used is because there is a direct mapping of single hexadecimal digit to exactly four binary digits, so hex is a compact way of representing bit patterns. For an experienced embedded developer, mentally converting a bit-pattern to hex and vice versa becomes second nature. If the values were decimal, the representation would bear no direct relationship to the bit pattern, and the conversion or mental visualisation of the bit pattern less simple.
The hex digit to binary pattern conversion is as follows:
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
A 1010
B 1011
C 1100
D 1101
E 1110
F 1111
0xFC = 11111100
0x60 = 1100000
0xDA = 11011010
....
you need an array of hex numbers, most probably you have connected some sort of device to portA, and in this device
0xFC or 11111100 means display 0,(when portA pins 7,6,5,4,3,2, are high and 1,0 are low this device will display 0
0x60 or 11000000 means display 1(when PortA pins 7,6 are high and the rest low, this device will display 1.
and so on..
The memory locations in the microcontroller are 8 bits wide so 16 I/O will require two 8 bit registers called PORTA and PORTB. in your case its only 8bits wide ie. 8 I/O pins per PORTA, another 8 for PORTB and so on.
the outputs of these ports are controlled by the 8bits..
Suppose we wish to turn on an LED which we are going to connect to bit 4 on PORTB. We first of all have to instruct the microcontroller to ensure that PORTB bit 4 is an output.(the micro needs to know if ports are outputs are inputs you cant just plug stuff in)
in a pic micro you would say TRIA = 0x00010000 this tell the micro portB4 is an output.Now that we have said its an output, PORTA = 0b00010000 sets this portB4 to a high voltage, in other words this will illuminate the LED or whatever you have connected to the port.
PORTA = 0b00000000 // turns off PORTA outputs,
PORTA = 0b10000000 // turns on PORTA pin 7
The hexadecimal values its just a notation, the first letter represents the first 4 bits of your int and the other the other four bits because you are declaring a const uint8 variable wich means an unsigned integer of 8 bits, this is an integer but without sign, the bit of the sign is removed, so it can store 2^8 posibles values.
I'm just answering the first question. Hope it help!!
From Microchip sample code
PR2 = 2083u; /* Timer2 Period, 19.2 kHz */
How does 2083u correspond to 19.2 kHz, which is
1 / 19.2E03 = 52.083u
They don't correspond at all. Mistake by Microchip?
PR2 = 2083U
makes TIMER2 trigger every 2083 CPU cycles. Calculating
52.083 us / 2083 = 25 ns
1 / 25 ns = 40 MHz
we can conclude that the processor is probably running at FCY = 40 MHz in the example.
The letter u in PR2 = 2038u; does not mean microseconds; it is a C language syntax that makes the integer literal unsigned. See Signedness (Wikipedia).
Setting PR2 to 2083 means that the timer triggers every 2084 (not 2083) clock cycles. When you calculate a timer period, you always have to subtract 1 because the timer value is zero-based.