Autor Tema: Algoritmo para cargar un registro en serie "por la izquierda"  (Leído 2190 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Algoritmo para cargar un registro en serie "por la izquierda"
« en: 27 de Septiembre de 2008, 01:43:10 »
Cuando recibimos un dato en serie, un bit tras otro, lo habitual es recibir primero el MSB e ir cargando el registro mediante desplazamientos a la izquierda:

Código: Javascript
  1. while (recibiendo)
  2.     Dato = Dato<<1 + BitRecibido;

Sin embargo, en un dispositivo que estoy utilizando, la comunicación comienza por el LSB, lo cual complica la historia así:
Código: Javascript
  1. while (recibiendo)
  2.     Dato = Dato>>1 + BitRecibido<<23; // el registro es de 24 bits

A primera vista el código es igual, pero cuando se compila uno y otro, la diferencia es de 30 ciclos de instrucción a favor del primer algoritmo.
¿Se os ocurre alguna manera de cargar el dato con menos consumo de instrucciones?

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #1 en: 27 de Septiembre de 2008, 05:05:52 »
Prueba con esto o por lo menos investígalo:

Código: C#
  1. while (recibiendo){
  2.       Dato = Dato + BitRecibido;
  3.       rotate_right(&dato,8);
  4.    }

Teniendo en cuenta que Dato la he declarado como int32: Recojo el bit en Dato.0 y lo roto hacia la derecha 8 veces para moverlo hasta Data.24 ¡¡¡ No se si funciona !! pero el rotate es mas corto que el <<23

Se supone que al rotar a la derecha el bit.0 pasa a ser el bit.n y todos los demás quedan movidos una posición a la derecha, que no es como el shift que añade ceros por la izquierda o por la derecha dependiendo de en qué dirección shifteemos.

Comparando compilados:
Código: ASM
  1. ....................
  2. ....................    while (recibiendo)
  3. ....................       Dato = Dato<<1 + BitRecibido;
  4. 0024:  BTFSS  09.1
  5. 0026:  BRA    0046
  6. 0028:  MOVLW  00
  7. 002A:  BTFSC  09.0
  8. 002C:  MOVLW  01
  9. 002E:  ADDLW  01
  10. 0030:  MOVWF  0A
  11. 0032:  MOVF   0A,F
  12. 0034:  BZ    0044
  13. 0036:  BCF    FD8.0
  14. 0038:  RLCF   05,F
  15. 003A:  RLCF   06,F
  16. 003C:  RLCF   07,F
  17. 003E:  RLCF   08,F
  18. 0040:  DECFSZ 0A,F
  19. 0042:  BRA    0036
  20. 0044:  BRA    0024
  21. ....................
  22. ....................    while (recibiendo)
  23. ....................       Dato = Dato>>1 + BitRecibido<<23;
  24. 0046:  BTFSS  09.1
  25. 0048:  BRA    00A0
  26. 004A:  MOVLW  00
  27. 004C:  BTFSC  09.0
  28. 004E:  MOVLW  01
  29. 0050:  ADDLW  01
  30. 0052:  MOVWF  0A
  31. 0054:  MOVFF  08,0E
  32. 0058:  MOVFF  07,0D
  33. 005C:  MOVFF  06,0C
  34. 0060:  MOVFF  05,0B
  35. 0064:  MOVF   0A,F
  36. 0066:  BZ    0076
  37. 0068:  BCF    FD8.0
  38. 006A:  RRCF   0E,F
  39. 006C:  RRCF   0D,F
  40. 006E:  RRCF   0C,F
  41. 0070:  RRCF   0B,F
  42. 0072:  DECFSZ 0A,F
  43. 0074:  BRA    0068
  44. 0076:  CLRF   05
  45. 0078:  CLRF   06
  46. 007A:  RLCF   0B,W
  47. 007C:  MOVWF  07
  48. 007E:  RLCF   0C,W
  49. 0080:  MOVWF  08
  50. 0082:  RLCF   07,F
  51. 0084:  RLCF   08,F
  52. 0086:  RLCF   07,F
  53. 0088:  RLCF   08,F
  54. 008A:  RLCF   07,F
  55. 008C:  RLCF   08,F
  56. 008E:  RLCF   07,F
  57. 0090:  RLCF   08,F
  58. 0092:  RLCF   07,F
  59. 0094:  RLCF   08,F
  60. 0096:  RLCF   07,F
  61. 0098:  RLCF   08,F
  62. 009A:  MOVLW  80
  63. 009C:  ANDWF  07,F
  64. 009E:  BRA    0046
  65. ....................
  66. ....................    while (recibiendo){
  67. 00A0:  BTFSS  09.1
  68. 00A2:  BRA    00C8
  69. ....................       Dato = Dato + BitRecibido;
  70. 00A4:  MOVLW  00
  71. 00A6:  BTFSC  09.0
  72. 00A8:  MOVLW  01
  73. 00AA:  ADDWF  05,F
  74. 00AC:  MOVLW  00
  75. 00AE:  ADDWFC 06,F
  76. 00B0:  ADDWFC 07,F
  77. 00B2:  ADDWFC 08,F
  78. ....................       rotate_right(&dato,8);
  79. 00B4:  RRCF   05,W
  80. 00B6:  RRCF   0C,F
  81. 00B8:  RRCF   0B,F
  82. 00BA:  RRCF   0A,F
  83. 00BC:  RRCF   09,F
  84. 00BE:  RRCF   08,F
  85. 00C0:  RRCF   07,F
  86. 00C2:  RRCF   06,F
  87. 00C4:  RRCF   05,F
  88. ....................    }

 
« Última modificación: 27 de Septiembre de 2008, 05:09:04 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #2 en: 27 de Septiembre de 2008, 07:41:46 »
Ea, me encanta que hagan preguntas inteligentes ...  :mrgreen:

Prueba con esto, recoge bits sobre el bit 23 pero previamente rota a la derecha una posición. Es corto y parece que tiene buena pinta.

Código: C#
  1. Dato>>=1;
  2.    if(BitRecibido) bit_set(Dato,23); else bit_clear(Dato,23);

Que compilado se queda solo en 10 instrucciones.

Código: ASM
  1. ....................    Dato>>=1;
  2. 0436:  BCF    FD8.0
  3. 0438:  RRCF   1C,F
  4. 043A:  RRCF   1B,F
  5. 043C:  RRCF   1A,F
  6. 043E:  RRCF   19,F
  7. ....................    if(BitRecibido) bit_set(Dato,23); else bit_clear(Dato,23);
  8. 0440:  BTFSS  1D.0
  9. 0442:  BRA    0448
  10. 0444:  BSF    1B.7
  11. 0446:  BRA    044A
  12. 0448:  BCF    1B.7
  13. ....................
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #3 en: 27 de Septiembre de 2008, 07:45:28 »
Y si lo pones de esta forma ocupas solo 8 instrucciones  :mrgreen: :mrgreen: :mrgreen:

Código: C#
  1. Dato>>=1;
  2.    bit_clear(Dato,23);
  3.    if(BitRecibido) bit_set(Dato,23);

Código: ASM
  1. ....................    Dato>>=1;
  2. 0436:  BCF    FD8.0
  3. 0438:  RRCF   1C,F
  4. 043A:  RRCF   1B,F
  5. 043C:  RRCF   1A,F
  6. 043E:  RRCF   19,F
  7. ....................    bit_clear(Dato,23);
  8. 0440:  BCF    1B.7
  9. ....................    if(BitRecibido) bit_set(Dato,23);
  10. 0442:  BTFSC  1D.0
  11. 0444:  BSF    1B.7
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #4 en: 27 de Septiembre de 2008, 07:49:07 »
Interesante idea, Don Diego, pero tal y como estaba no funciona. El parámetro del rotate es el nº de bytes de la estructura con la que vas a trabajar, y por tanto había que ponerle 4 para un int32. Dejo el código que funciona según tu método (he probado con 3 bytes a partir del segundo para rotar los 24 bits pero no lo he conseguido.)

Código: Javascript
  1. for (i=0;i<24;i++) {
  2.       EsperaFlancoBajada;
  3.       Posicion = Posicion + input(PIN_B0);
  4.       rotate_right(&Posicion,4);
  5.       EsperaFlancoSubida;
  6.    }
  7.    for (i=0;i<8;i++)
  8.       rotate_right(&Posicion,4);

Con este código se compila en 66 instrucciones y 32 iteraciones.

Buscando opciones, he llegado a una que me gusta. Es la siguiente:

Código: Javascript
  1. for (i=0;i<24;i++) {
  2.       EsperaFlancoBajada;
  3.       Posicion=Posicion>>1;
  4.       if (input(PIN_B0))
  5.          Posicion=Posicion+0b100000000000000000000000;
  6.       EsperaFlancoSubida;
  7.    }

Esta se compila en 48 instrucciones con 24 iteraciones.

De todas formas, miraré de nuevo lo del rotate con sólo 3 bytes, a ver si lo saco.

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #5 en: 27 de Septiembre de 2008, 07:55:01 »
Olvídate de rotates y mira mi tercer post. Funciona porque lo he probado y es ultra-corto.  :mrgreen:

Código: C#
  1. Dato>>=1;
  2.   bit_clear(Dato,23);
  3.   if(BitRecibido) bit_set(Dato,23);

Anotados los ciclos se ejecuta en 10 ciclos de instruccion (40 de reloj)

Código: ASM
  1. ....................    Dato>>=1;
  2. 0436:1  BCF    FD8.0
  3. 0438:1  RRCF   1C,F
  4. 043A:1  RRCF   1B,F
  5. 043C:1 RRCF   1A,F
  6. 043E:1 RRCF   19,F
  7. ....................    bit_clear(Dato,23);
  8. 0440:1  BCF    1B.7
  9. ....................    if(BitRecibido) bit_set(Dato,23);
  10. 0442:3  BTFSC  1D.0
  11. 0444:1  BSF    1B.7

« Última modificación: 27 de Septiembre de 2008, 08:00:17 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 18286
    • MicroPIC
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #6 en: 27 de Septiembre de 2008, 08:00:59 »
Espectacular, Don Diego. Sólo 34 ciclos y 24 iteraciones.

Código: Javascript
  1. for (i=0;i<24;i++) {
  2.       EsperaFlancoBajada;
  3.       Posicion=Posicion>>1;
  4.       if (input(PIN_B0))
  5.          bit_set(Posicion,23);
  6.       EsperaFlancoSubida;
  7.          
  8.    }

A sus pies, maestro

P.D.: el bit_clear me lo he cargado porque al principio hago Posicion=0;

Desconectado RedPic

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 5544
    • Picmania by Redraven
Re: Algoritmo para cargar un registro en serie "por la izquierda"
« Respuesta #7 en: 27 de Septiembre de 2008, 08:03:01 »
Así me gusta, que me hagas caso. Ja, ja, ja  :D :D :D

El bit_clear lo puse pa-por-si-acaso, que los bit´s flotantes los carga el diablo.  :mrgreen:

Es que últimamente con lo del Detectando Flancos de subida (y de bajada) con un 18F4550 tengo los ciclos a flor de piel. Ja, ja, ja  :D :D :D
« Última modificación: 27 de Septiembre de 2008, 08:07:23 por RedPic »
Contra la estupidez los propios dioses luchan en vano. Schiller
Mi Güeb : Picmania


 

anything