memcpy leo que es lo más rápido, pero no estoy seguro si permite copiar una matriz tridimensional completa sobre otra idéntica. Mi duda radica en que no se como está organizada internamente en memoria una matriz tridimensional, para poder usar un puntero de origen a destino con posiciones contiguas de memoria. He visto algún ejemplo en el que solo copian una de las dimensiones completas de una matriz bidimensional o tridimensional, pero no la matriz al completo, o que todos los elementos deben de estar ubicados en posiciones de memoria contiguas tanto en origen como en destino.
Mi problema, es que tengo una matriz que se llena a partir de datos que entran por SPI/DMA. Por eso cuando esa matriz está llena, como la tengo que enviar por UDP (previo proceso y troceado de esos datos), necesito copiarla rápido a otra matriz de trabajo, porque si trabajo sobre la matriz original, mientras la estoy leyendo, ya se está actualizando por otro lado y me altera los datos.
Mi idea es copiar la matriz original y trabajar sobre la copia, mientras el resto de proceso puede seguir actualizando la matriz original.
Eso de configurar el DMA para que de manera alternada y automática vuelque en dos buffers, no se como hacerlo. Puedo simularlo por software, usando un campo a modo de switch, para que con un IF vuelque los datos del buffer a una u otra matriz, para ir alternando la matriz de trabajo.
De todas formas el buffer del DMA no es con el que trabajo directamente, ese buffer se copia con un memcpy a la matriz multidimensional, usando tres índices, y es cuando la matriz está totalmente llena, cuando se pasa a una función para procesarla.
Y la cosa aún se complica más, porque la matriz se llena como si fuera un registro de desplazamiento, así tampoco se podrían alternar. No puedo meter 3 planos de datos a una matriz, y luego pasarme a la otra, los datos que van entrando por el DMA van empujando a los planos de la matriz, de manera que siempre estén los 3 últimos que han entrado. Si las alternara, habría un vacío de 3 planos que dejarían de desplazar los datos en cada matriz.
Yo creo que con un memcpy se puede hacer un memcpy(&array2,&array1,sizeof(array2));, que duplique el array, creo que es algo bastante rápido.
No necesariamente la matriz tiene que ser tridimensional para representar la imagen.
Recuerda que el DMA tiene la opción de levantar una interrupción cuando el buffer está a la mitad, por lo que podrías usar esa característica para simular dos buffer en un mismo arreglo o, en su defecto podrías crear una estructura, como te lo había comentado en otro hilo, donde tengas dos buffers. En cualquier caso, a la hora de que el DMA del SPI levante una interrupción, se le indica donde tiene que almacenar los siguientes datos (en el caso de dos buffers) y en ambos caso la rutina que envía los datos por UDP trabaja de forma independiente del DMA del SPI, ya que en la rutina de interrupción se indicaría cual buffer o sección contiene datos válidos.
Así te evitas la copia de datos a otra región de memoria.
Lo que no quiero es copiar la matriz barriéndola con bucles "for", eso me parece una chapuza, tiene que haber algo para hacer una copia directa.
ROW/COLUM iteration in two dimentional Array: Total Time: 1729.835000 ms
One dimentional Array: Total Time: 432.439000 ms
Ratio: 4.000183
CitarLo que no quiero es copiar la matriz barriéndola con bucles "for", eso me parece una chapuza, tiene que haber algo para hacer una copia directa.
Te equivocaste de lenguaje parece, Y por mas que el lenguaje lo haga mucho mas facil como seria un overload del operador asignacion en C++ lo seguirias haciendo con un for.
Estas intentando correr contra el tiempo y no hay otra forma de realizar el copiado mas que con DMA si es que no queres usar un for/while como lo hace el memcpy por dentro y punteros.
Por otra parte el tema de usar 2 buffers es la solucion que estas buscando. Ya que tu problema hasta ahora es que estas corriendo como loco porque los datos te llegan de nuevo y no tenes donde ponerlos y tampoco lugar para donde procesarlos.
Si, pero un memcpy no es lo que estas buscando vos, ya que tu problema es la velocidad de ejecucion respecto al llenado del buffer. Lo que te digo es que busques como realizar con DMA un doble buffer, asi mientras seguis llenando tenes tiempo de realizar esa copia.
//** Esta es la matriz original
uint16_t planes[PLANE_SIZE * PLANE_COUNT];
typedef uint16_t wpc_plane[ROW_COUNT][ROW_LENGTH];
wpc_plane* wpc_planes = (wpc_plane*) planes;
// Aqui he definido otra para copiar la original con memcpy
uint16_t planes2[PLANE_SIZE * PLANE_COUNT];
typedef uint16_t wpc_plane2[ROW_COUNT][ROW_LENGTH];
wpc_plane2* wpc_planes2 = (wpc_plane2*) planes2;
// Aqui el memcpy para copiar una matriz sobre otra
memcpy(wpc_planes2, wpc_planes, sizeof(wpc_planes2));
ROW_COUNT = 100 ; ROW_LENGTH 3
sizeof(wpc_planes2) = 4
sizeof(*wpc_planes2) = 600
sizeof(wpc_planes2) te da el tamaño del puntero que va a ser dependiente de la arquitectura, como es de 32 bits, sólo te va a copiar los primeros 4 bytes. Tienes que hacerlo de la siguiente forma sizeof(*wpc_planes2)
Me imagino que
PLANE_SIZE * PLANE_COUNT = ROW_COUNT * ROW_LENGTH
sizeof(wpc_planes2) te da el tamaño del puntero que va a ser dependiente de la arquitectura, como es de 32 bits, sólo te va a copiar los primeros 4 bytes. Tienes que hacerlo de la siguiente forma sizeof(*wpc_planes2)
uint16_t planes[PLANE_SIZE * PLANE_COUNT];
typedef uint16_t wpc_plane[ROW_COUNT][ROW_LENGTH];
wpc_plane* wpc_planes = (wpc_plane*) planes;#define ROW_COUNT 32
#define COL_COUNT 128
#define ROW_LENGTH (COL_COUNT / 16)
#define COLOR_DEPTH 24
#define PLANE_COUNT 4
#define PLANE_SIZE ROW_COUNT * ROW_LENGTH
uint16_t planes[PLANE_SIZE * PLANE_COUNT];
PLANE_SIZE*PLANE_COUNT = ROW_COUNT*ROW_LENGTH * PLANE_COUNT = 32*8*4 = 1024
typedef uint16_t wpc_plane[ROW_COUNT][ROW_LENGTH];
ROW_COUNT*ROW_LENGTH = 32*8 = 256
wpc_plane* wpc_planes = (wpc_plane*) planes;
sizeof(*wpc_planes2)*PLANE_COUNT
sizeof(wpc_planes2) = 8
sizeof(*wpc_planes2) = 512
sizeof(*wpc_planes2)*PLANE_COUNT = 2048
sizeof(planes2) = 2048