Hi,
does anybody try to use one pin of 4-bit port for transmit/receive S/PDIF stream?
I have tested app_example_tx from sc_spdif-1.3.4alpha0.
When I output S/PDIF stream to 1-bit port (as described in module documentation) it works correctly. Output frequency is about 1.778 MHz.
When I output S/PDIF stream to pin 0 of 4-bit port (3 other pins are not connected on board) output frequency is about 7.060 MHz and there is SYNC ERROR on the receiver.
Use 4-bit port for S/PDIF TX/RX
-
- Experienced Member
- Posts: 119
- Joined: Mon Sep 15, 2014 1:32 pm
-
- Respected Member
- Posts: 347
- Joined: Wed Jan 27, 2016 5:21 pm
Hi,
You won't be able to use it for receiving S/PDIF - the receiver relies on the serialiser on the 1-bit port.
For output you may be able to use a 4-bit port, but you would have to spread out the tables so that it runs at a quarter of the speed. As it is, you will be sending every fourth bit to pin 0, bits (4n+1) to pin 1, etc.
Cheers,
Henk
You won't be able to use it for receiving S/PDIF - the receiver relies on the serialiser on the 1-bit port.
For output you may be able to use a 4-bit port, but you would have to spread out the tables so that it runs at a quarter of the speed. As it is, you will be sending every fourth bit to pin 0, bits (4n+1) to pin 1, etc.
Cheers,
Henk
-
- Experienced Member
- Posts: 119
- Joined: Mon Sep 15, 2014 1:32 pm
Henk,
as I understand:
If output port is 1-bit port.
If output port is 4-bit port, for example, P4D.
So, to output all 'data' bits only to P4D0, 'data' must be
Is my reasoning correct?
as I understand:
If output port is 1-bit port.
Code: Select all
out buffered port:32 p = XS1_PORT_1O;
unsigned data = 0b[b31 b30 ... b1 b0], b0-b31 - bits of 'data' value
p <: data;
port output = b0 b1 b2 b3 b4 ... b31
Code: Select all
out buffered port:32 p = XS1_PORT_4D;
unsigned data = 0b[b31 b30 ... b1 b0], b0-b31 - bits of 'data' value
p <: data;
P4D0 output = b0 b4 b8 ... b28
P4D1 output = b1 b5 b9 ... b29
P4D2 output = b2 b6 b10... b30
P4D3 output = b3 b7 b11... b31
So, to output all 'data' bits only to P4D0, 'data' must be
Code: Select all
unsigned data0 = 0b[b7 0 0 0 b6 0 0 0 b5 0 0 0 ... b0 0 0 0]
unsigned data1 = 0b[b15 0 0 0 b14 0 0 0 b13 0 0 0 ... b8 0 0 0]
unsigned data2 = 0b[b23 0 0 0 b22 0 0 0 b21 0 0 0 ... b16 0 0 0]
unsigned data3 = 0b[b31 0 0 0 b30 0 0 0 b29 0 0 0 ... b24 0 0 0]
p <: data0;
p <: data1;
p <: data2;
p <: data3;
P4D0 output = b0 b1 b2 ... b31
P4D1 output = 0 0 0 ... 0
P4D2 output = 0 0 0 ... 0
P4D3 output = 0 0 0 ... 0
-
- Respected Member
- Posts: 347
- Joined: Wed Jan 27, 2016 5:21 pm
Yes - completely correct.
If you use xCORE200 you can use the zip instruction twice to do this.
Zip (b31 b30 b29..b0) with (0 0 0 .. 0) and you get two words (b31 0 b30 0 ... b16 0) and (b15 0 b14 0 b13 0 ... b0 0); do this once more and you get four words (b31 0 0 0 b30 0 0 0) etc.
Even though this is only two instructions, it very much unbalances your rhythm of IO and computation.
However, if you have a spare logical core in your system, just make the SPDIF TX thread output to a channel, and write a single while loop that reads a word, splits it into four words using the ZIP instructions, and output the four words.
Cheers,
Henk
If you use xCORE200 you can use the zip instruction twice to do this.
Zip (b31 b30 b29..b0) with (0 0 0 .. 0) and you get two words (b31 0 b30 0 ... b16 0) and (b15 0 b14 0 b13 0 ... b0 0); do this once more and you get four words (b31 0 0 0 b30 0 0 0) etc.
Even though this is only two instructions, it very much unbalances your rhythm of IO and computation.
However, if you have a spare logical core in your system, just make the SPDIF TX thread output to a channel, and write a single while loop that reads a word, splits it into four words using the ZIP instructions, and output the four words.
Cheers,
Henk
-
- Experienced Member
- Posts: 119
- Joined: Mon Sep 15, 2014 1:32 pm
Henk,
I try to use ZIP instruction, but I get strange result.
I run program in simulator and watch values in debugger
The same is with other steps
I try to use ZIP instruction, but I get strange result.
I run program in simulator and watch values in debugger
Code: Select all
unsigned h, l;
h = 0xFFFFFFFF;
l = 0;
asm ("zip %0 , %1 , 4" : "=r"(h) , "=r"(l) : "r"(h) , "r"(l)); // zip with 2^4=16 bit step
// I expect to see h = 11..1100..00, l = 11..1100..00, but h = 00..0011..11, l = 00..0011..11
Code: Select all
unsigned h, l;
h = 0xFFFFFFFF;
l = 0;
asm ("zip %0 , %1 , 3" : "=r"(h) , "=r"(l) : "r"(h) , "r"(l)); // zip with 2^3=8 bit step
// h = l = 0..01..10..01..10..01..10..01..1
Code: Select all
unsigned h, l;
h = 0xFFFFFFFF;
l = 0;
asm ("zip %0 , %1 , 0" : "=r"(h) , "=r"(l) : "r"(h) , "r"(l)); // zip with 2^0=1 bit step
// h = l = 01..01
-
- Respected Member
- Posts: 347
- Joined: Wed Jan 27, 2016 5:21 pm
I am wondering whether something funky happened with the asm
Try using these:
(from xs1.h)
Try using these:
Code: Select all
/**
* Unzip a 64-bit value into two 32-bit values, with a granularity of
* bits, bit pairs, nibbles, bytes or byte pairs.
* \param value The 64-bit zipped value.
* \param log_granularity The logarithm of the granularity.
* \return Two 32-bit unzipped values.
*/
{unsigned int, unsigned int} unzip(unsigned long long value,
unsigned int log_granularity);
/**
* Zip two 32-bit values into a single 64-bit value, with a granularity of
* bits, bit pairs, nibbles, bytes or byte pairs.
* \param value1 The first 32-bit value.
* \param value2 The second 32-bit value.
* \param log_granularity The logarithm of the granularity.
* \return The 64-bit zipped value.
*/
unsigned long long zip(unsigned int value1, unsigned int value2,
unsigned int log_granularity);
-
- Experienced Member
- Posts: 119
- Joined: Mon Sep 15, 2014 1:32 pm
It works correctly.
-
- Experienced Member
- Posts: 119
- Joined: Mon Sep 15, 2014 1:32 pm
I have found a mistake in one of my previous post
For P4D0 pin output correct values are:
In that case output "b0 b1 b2 ... b31" will be on P4D3 pin.So, to output all 'data' bits only to P4D0, 'data' must be
Code: Select all
unsigned data0 = 0b[b7 0 0 0 b6 0 0 0 b5 0 0 0 ... b0 0 0 0] unsigned data1 = 0b[b15 0 0 0 b14 0 0 0 b13 0 0 0 ... b8 0 0 0] unsigned data2 = 0b[b23 0 0 0 b22 0 0 0 b21 0 0 0 ... b16 0 0 0] unsigned data3 = 0b[b31 0 0 0 b30 0 0 0 b29 0 0 0 ... b24 0 0 0] p <: data0; p <: data1; p <: data2; p <: data3; P4D0 output = b0 b1 b2 ... b31 P4D1 output = 0 0 0 ... 0 P4D2 output = 0 0 0 ... 0 P4D3 output = 0 0 0 ... 0
For P4D0 pin output correct values are:
Code: Select all
unsigned data0 = 0b[0 0 0 b7 0 0 0 b6 0 0 0 ... 0 0 0 b0]
unsigned data1 = 0b[0 0 0 b15 0 0 0 b14 0 0 0 ... 0 0 0 b8]
unsigned data2 = 0b[0 0 0 b23 0 0 0 b22 0 0 0 ... 0 0 0 b16]
unsigned data3 = 0b[0 0 0 b31 0 0 0 b30 0 0 0 ... 0 0 0 b24]
-
- Experienced Member
- Posts: 119
- Joined: Mon Sep 15, 2014 1:32 pm
I replace all partout() function calls in SpdifTransmit.xc file with calls to function my_partout()
It seems it work!
Code: Select all
#include <xs1.h>
void my_partout(out buffered port:32 p, unsigned n, unsigned val)
{
if (n == 16)
// send 16 bits to port in 2 steps: insert zeroes in each 8-bit part twice and send 32 bit to port, repeat
{
unsigned long long res = 0; // 64-bit value
unsigned int data = val & 0xFF; // get low 8-bit = [x x x x ... b7 b6 ... b0]
res = zip(0, data, 0); // convert to [0 x 0 x ... b7 0 b6 0 ... 0 b0]
res &= 0xFFFFFFFF; // get low 32-bit part
data = zip(0, res, 0); // convert again to [0 0 0 x 0 0 0 x ... b7 0 0 0 b6 ... 0 0 0 b0]
partout(p, 32, data); // send low 32 bits to port [0 0 0 b7 0 0 0 b6 ... 0 0 0 b0]
data = (val >> 8) & 0xFF; //get bits from 15 to 8 = [x x x x ... b15 b14 ... b8]
res = zip(0, data, 0); // convert to [0 x 0 x ... b15 0 b14 0 ... 0 b8]
res &= 0xFFFFFFFF; // get low 32-bit part
data = zip(0, res, 0); // convert again to [0 0 0 x 0 0 0 x ... b15 0 0 0 b14 ... 0 0 0 b8]
partout(p, 32, data); // send low 32 bits to port [0 0 0 b15 0 0 0 b14 ... 0 0 0 b8]
}
else if (n == 8)
// send 8 bits to port in 1 step: insert zeroes twice and send 32 bit to port
{
unsigned long long res = 0;
unsigned int data = val & 0xFF;
res = zip(0, data, 0);
res &= 0xFFFFFFFF;
data = zip(0, res, 0);
partout(p, 32, data);
}
}
-
- Respected Member
- Posts: 347
- Joined: Wed Jan 27, 2016 5:21 pm
Great.
I suggest to replace the remaining calls to partout(..., 32, ...) with ordinary <:
Partout is designed to do a partial output, but it limits buffering.
<: is guaranteed to make the most of buffering.
Cheers,
Henk
I suggest to replace the remaining calls to partout(..., 32, ...) with ordinary <:
Partout is designed to do a partial output, but it limits buffering.
<: is guaranteed to make the most of buffering.
Cheers,
Henk