Перейти к содержанию
    

Rst7

Модератор
  • Постов

    4 619
  • Зарегистрирован

  • Победитель дней

    2

Сообщения, опубликованные Rst7


  1. И возвращаясь к передаче кучи переменных.

    Конечно, протокол обмена надо делать другим. Сначала складывать все long, потом все short. Итого код выглядит так:

    void Dump(long *d, long **s, unsigned int len32, unsigned int len16)
    {
      while(len32)
      {
        *d++=*(*s++);
        len32--;
      }
      unsigned short **_s;
      unsigned short *_d;
      _s=(unsigned short**)s;
      _d=(unsigned short*)d;
      while(len16)
      {
        *_d++=*(*_s++);
        len16--;
      }
    }
    	

    Самое занятное - это результат компиляции такого тупого кода:

     

     

    Spoiler
    
    		        4          void Dump(long *d, long **s, unsigned int len32, unsigned int len16)
    		      5          {
    		   \                     Dump: (+1)
    		   \        0x0   0xB470             PUSH     {R4-R6}
    		   \        0x2   0x4604             MOV      R4,R0
    		   \        0x4   0xB312             CBZ.N    R2,??Dump_0
    		   \        0x6   0xF012 0x0003      ANDS     R0,R2,#0x3
    		   \        0xA   0xD006             BEQ.N    ??Dump_1
    		      6            while(len32)
    		      7            {
    		      8              *d++=*(*s++);
    		   \                     ??Dump_2: (+1)
    		   \        0xC   0xF851 0x5B04      LDR      R5,[R1], #+4
    		   \       0x10   0x682E             LDR      R6,[R5, #+0]
    		   \       0x12   0xF844 0x6B04      STR      R6,[R4], #+4
    		      9              len32--;
    		   \       0x16   0x1E40             SUBS     R0,R0,#+1
    		   \       0x18   0xD1F8             BNE.N    ??Dump_2
    		   \                     ??Dump_1: (+1)
    		   \       0x1A   0x0892             LSRS     R2,R2,#+2
    		   \       0x1C   0xF000 0x8016      BEQ.W    ??Dump_0
    		   \                     ??Dump_3: (+1)
    		   \       0x20   0xF851 0x0B04      LDR      R0,[R1], #+4
    		   \       0x24   0x6800             LDR      R0,[R0, #+0]
    		   \       0x26   0xF844 0x0B04      STR      R0,[R4], #+4
    		   \       0x2A   0x1E52             SUBS     R2,R2,#+1
    		   \       0x2C   0xF851 0x5B04      LDR      R5,[R1], #+4
    		   \       0x30   0x682D             LDR      R5,[R5, #+0]
    		   \       0x32   0xF844 0x5B04      STR      R5,[R4], #+4
    		   \       0x36   0xF851 0x0B04      LDR      R0,[R1], #+4
    		   \       0x3A   0x6800             LDR      R0,[R0, #+0]
    		   \       0x3C   0xF844 0x0B04      STR      R0,[R4], #+4
    		   \       0x40   0xF851 0x5B04      LDR      R5,[R1], #+4
    		   \       0x44   0x682D             LDR      R5,[R5, #+0]
    		   \       0x46   0xF844 0x5B04      STR      R5,[R4], #+4
    		   \       0x4A   0xD1E9             BNE.N    ??Dump_3
    		     10            }
    		     11            unsigned short **_s;
    		     12            unsigned short *_d;
    		     13            _s=(unsigned short**)s;
    		     14            _d=(unsigned short*)d;
    		   \                     ??Dump_0: (+1)
    		   \       0x4C   0xB313             CBZ.N    R3,??Dump_4
    		   \       0x4E   0xF013 0x0003      ANDS     R0,R3,#0x3
    		   \       0x52   0xD006             BEQ.N    ??Dump_5
    		     15            while(len16)
    		     16            {
    		     17              *_d++=*(*_s++);
    		   \                     ??Dump_6: (+1)
    		   \       0x54   0xF851 0x2B04      LDR      R2,[R1], #+4
    		   \       0x58   0x8815             LDRH     R5,[R2, #+0]
    		   \       0x5A   0xF824 0x5B02      STRH     R5,[R4], #+2
    		     18              len16--;
    		   \       0x5E   0x1E40             SUBS     R0,R0,#+1
    		   \       0x60   0xD1F8             BNE.N    ??Dump_6
    		   \                     ??Dump_5: (+1)
    		   \       0x62   0x089B             LSRS     R3,R3,#+2
    		   \       0x64   0xF000 0x8016      BEQ.W    ??Dump_4
    		   \                     ??Dump_7: (+1)
    		   \       0x68   0xF851 0x0B04      LDR      R0,[R1], #+4
    		   \       0x6C   0x8800             LDRH     R0,[R0, #+0]
    		   \       0x6E   0xF824 0x0B02      STRH     R0,[R4], #+2
    		   \       0x72   0x1E5B             SUBS     R3,R3,#+1
    		   \       0x74   0xF851 0x2B04      LDR      R2,[R1], #+4
    		   \       0x78   0x8812             LDRH     R2,[R2, #+0]
    		   \       0x7A   0xF824 0x2B02      STRH     R2,[R4], #+2
    		   \       0x7E   0xF851 0x0B04      LDR      R0,[R1], #+4
    		   \       0x82   0x8800             LDRH     R0,[R0, #+0]
    		   \       0x84   0xF824 0x0B02      STRH     R0,[R4], #+2
    		   \       0x88   0xF851 0x2B04      LDR      R2,[R1], #+4
    		   \       0x8C   0x8812             LDRH     R2,[R2, #+0]
    		   \       0x8E   0xF824 0x2B02      STRH     R2,[R4], #+2
    		   \       0x92   0xD1E9             BNE.N    ??Dump_7
    		     19            }
    		     20          }
    		   \                     ??Dump_4: (+1)
    		   \       0x94   0xBC70             POP      {R4-R6}
    		   \       0x96   0x4770             BX       LR               ;; return
    		 				
    			

     

    Если разворота циклов, сделанных самим компилятором, недостаточно, то можно и самому выступить по написанию Duff Device, что несложно. Но и этот код, прямо скажем, хуже совсем на копейку, нежели JIT, но на порядок проще.

  2. 1 minute ago, jcxz said:

    Вы же пользуетесь эмулятором для отладки? А зачем? Почему не подняться выше и не "посмотреть на алгоритм работы целиком"? И сразу аналитически найти все проблемы?

    Вы не поверите )))) Только отладочная печать и отладочное махание ножками. Математику отлаживаю на большом брате. Так что ни эмуляторы, ни железные отладчики я не использую.

    6 minutes ago, jcxz said:

    Тут дело в том, что некоторые радикально настроенные товарищи уверяют что знание ассемблера вообще не нужно. Вот с этим и не соглашаюсь.

    Ну для формошлепов и любителей "нагуглить готовое решение" - не нужно.

  3. 4 minutes ago, jcxz said:

    Нужно было сделать осциллографирование (в реальном времени) содержимого некоторых переменных в ПО.

    Дайте я догадаюсь ;) Это же надо было исключительно на этапе отладки? Неужели настолько там все друг с другом запутано, что не получилось отладить по-модульно, например, а не собирать переменные из кучи мест?

     

    5 minutes ago, jcxz said:

    Я Вам уже приводил пример - Вы так ничего и не ответили по существу: Например - данные поступают от АЦП. И как заставить АЦП присылать уже отсортированные данные, расскажите?

    В таком ключе на Ваш вопрос нет ответа. Надо подняться с уровня гайки М3 (поступающих данных от АЦП) и посмотреть на алгоритм работы целиком.

     

    Думаю, что все эти примеры показывают только одно - достаточно поверхностное отношение к системному проектированию.

     

    И главное, Вы не думайте, что я тут пропагандирую "никакого низкого уровня". Я сам большой любитель, например:

    Spoiler

    				
    			#pragma inline=forced
    		static long long MULLS(REG32 a, REG32 b)
    		{
    		  long long r;
    		  asm("SMULL %L0,%H0,%1,%2":"=Rp"(r):"r"(a),"r"(b));
    		  return r;
    		}				
    			//#define LL2FRACT_ROUND(VAR) (((VAR)&(1UL<<(FRACT_SHIFT-1))?(VAR)>>FRACT_SHIFT:((VAR)>>FRACT_SHIFT)+1))
    		//#define LL2FRACT_ROUND2(VAR) (((VAR)&(1UL<<(FRACT_SHIFT))?(VAR)>>(FRACT_SHIFT+1):((VAR)>>(FRACT_SHIFT+1))+1))				
    			#pragma inline=forced
    		static inline FRACT LL2FRACT_ROUND(long long r)
    		{
    		  asm("LSRS  %L0,%L0,%1":"+Rp"(r):"I"(FRACT_SHIFT):"cc"); //:);
    		  asm("ORR   %L0,%L0,%H0, LSL %1":"+Rp"(r):"I"(32-FRACT_SHIFT));
    		  asm("IT    CS\n"
    		      "ADDCS %L0,%L0,#+1":"+Rp"(r));
    		  return r;
    		}				
    			#pragma inline=forced
    		static inline FRACT LL2FRACT_ROUND2(long long r)
    		{
    		  asm("LSRS  %L0,%L0,%1":"+Rp"(r):"I"(FRACT_SHIFT+1):"cc"); //:);
    		  asm("ORR   %L0,%L0,%H0, LSL %1":"+Rp"(r):"I"(32-(FRACT_SHIFT+1)));
    		  asm("IT    CS\n"
    		      "ADDCS %L0,%L0,#+1":"+Rp"(r));
    		  return r;
    		}				
    			#pragma inline=forced
    		static inline FRACT FMULL(long a, long b)
    		{
    		  long long r = MULLS(a,b);
    		  return LL2FRACT_ROUND(r);
    		}				
    			#pragma inline=forced
    		static inline void Vector_Cross_Product(FRACT * vectorOut, FRACT const * v1, FRACT const * v2)
    		{
    		  vectorOut[0]= FMULL(v1[1],v2[2]) - FMULL(v1[2],v2[1]);
    		  vectorOut[1]= FMULL(v1[2],v2[0]) - FMULL(v1[0],v2[2]);
    		  vectorOut[2]= FMULL(v1[0],v2[1]) - FMULL(v1[1],v2[0]);
    		}				
    			static inline FRACT Vector_Dot_Product(FRACT const * vector1, FRACT const * vector2)
    		{
    		  long long r;
    		  asm("SMULL %L0,%H0,%1,%2":"=Rp"(r):"r"(vector1[0]),"r"(vector2[0]));
    		  asm("SMLAL %L0,%H0,%1,%2":"+Rp"(r):"r"(vector1[1]),"r"(vector2[1]));
    		  asm("SMLAL %L0,%H0,%1,%2":"+Rp"(r):"r"(vector1[2]),"r"(vector2[2]));
    		  return LL2FRACT_ROUND(r);
    		}				
    		#pragma inline=forced
    		static inline FRACT Vector_Dot_Product_Half(FRACT const * vector1, FRACT const * vector2)
    		{
    		  long long r;
    		  asm("SMULL %L0,%H0,%1,%2":"=Rp"(r):"r"(vector1[0]),"r"(vector2[0]));
    		  asm("SMLAL %L0,%H0,%1,%2":"+Rp"(r):"r"(vector1[1]),"r"(vector2[1]));
    		  asm("SMLAL %L0,%H0,%1,%2":"+Rp"(r):"r"(vector1[2]),"r"(vector2[2]));
    		  return LL2FRACT_ROUND2(r);
    		}
    

    Обратите внимание даже не на SMULL/SMLAL, а на IT CS/ADD

    Или 

    				
    			#define PRAMP() asm("ADD.N %0,%1":"+r"(sample):"r"(pwm_mask));
    		#define MRAMP() PRAMP()
    		  
    		#define PROCESS() \
    		  asm("ANDS.N %0,%1":"+r"(i1):"r"(pwm_mask)); \
    		  asm("ADD.N %0,%1":"+r"(i1):"r"(sample)); \
    		  *p++=i1; \
    		  				
    		  i=BLOCK_SIZE;
    		  do
    		  {
    		    sample=*input++;
    		    PROCESS(); PRAMP(); PROCESS(); PRAMP(); PROCESS(); PRAMP(); PROCESS(); PRAMP(); PROCESS(); PRAMP(); 
    		    PROCESS(); PRAMP(); PROCESS(); PRAMP(); PROCESS(); MRAMP(); PROCESS(); MRAMP(); PROCESS(); MRAMP(); 
    		    PROCESS(); MRAMP(); PROCESS(); MRAMP(); PROCESS(); MRAMP(); PROCESS(); MRAMP(); PROCESS();
    		  }
    		  while(--i);
    

     

    В общем - любим, умеем, практикуем, но в первую очередь стараемся не плодить кучу такого кода.

  4. 15 minutes ago, Arlleex said:

    В Cortex-M4 есть инструкции, которые могут за один проход сравнить соответствующие полуслова в двух регистрах или группу по 4 байта в двух регистрах:smile:

    Хотя это больше к вопросу о равномерности времени выполнения функции поиска, (детерминированности, что ли)...

    Это же и есть O(N). Т.е. время будет пропорционально количеству отсчетов. Коэффициент пропорциональности зависит от оптимизации в том числе, но куда полезнее подумать о возможности переделать алгоритм так, чтобы он превратился, например, в O(log2(N)). Думать надо вот в какую сторону - поиск максимума в отсортированном массиве - O(1). Можно считать - бесплатно. Прямой поиск - O(N). Возможно есть какие-то априорные знания о массиве, какие-то способы предсортировки данных, etc

    Просто может так оказаться, что завтра N будет равно не 512, а 4096, и никакой прямой поиск, написанный на ассемблере, не спасет.

  5. 52 minutes ago, jcxz said:

    Вариант в лоб с кучей функций вызываемых через указатели - это пожалуй самый тормозной будет.

    Нет, если установленных в 1 бит немного. Куда быстрее, чем куча if'ов.

    1 hour ago, jcxz said:

    Через LDM невозможно, так как переменные var0, ... раскиданы в памяти произвольным образом. varX - это условно так обозначено, чтобы описать задачу. А в общем случае - это могут быть и отдельные члены разных классов или структур.

    Простите, а кто вообще этот протокол обмена придумал? Зачем такие безумные сложности?

  6. Продолжаем разговор ;)

    11 hours ago, jcxz said:

    Есть массив из 512-и 16-битных беззнаковых чисел. Нужно найти максимальное число в этом массиве.

    Вот тут я бы пересмотрел вообще саму идеологию. Все эти прямые поиски - они все равно O(N), хоть на асме, хоть на Си. Как данные в массив попадают? Может быть их имеет смысл как-то предсортировать, если они попадают в массив малыми порциями, и этим вообще глобально улучшить ситуацию?

  7. Судя по 10В/м - это воздействие радиочастотных полей. Не должно нарушаться функционирование устройства. Походу местный дурачок неправильно заполнил протокол.

  8. Кстати, господа, пардон во втором примере за безумные приведения к FiiFunc*, но я просто не соображу, можно ли описать тип указателя на функцию, в которой один из параметров - указатель на такую функцию.

  9. 9 hours ago, jcxz said:

    вот другой пример: Есть код, который состоит из длинного полотенца:

    Мне кажется, Вы сильно загоняетесь.

    Решение в лоб:

    	unsigned long vars[64];
    	 
    	#define PROC(B,T,N) \
    	if (mask&(1UL<<B)) {T *_d; _d=d; *_d++=vars[N]; d=_d;}
    	 
    	void f(unsigned long mask, void *d)
    	{
    	  PROC(0,long,0);
    	  PROC(1,short,1);
    	  PROC(2,long,2);
    	  PROC(3,long,3);
    	  PROC(4,short,4);
    	  PROC(5,short,5);
    	  PROC(6,long,6);
    	  PROC(7,short,7);
    	}
    	

    дает вполне вменяемый результат:

    Spoiler

    				
    			   \                                 In section .bss, align 4
    		      2          unsigned long vars[64];
    		   \                     vars:
    		   \        0x0                      DS8 256
    		      3          
    		      4          #define PROC(B,T,N) \
    		      5          if (mask&(1UL<<B)) {T *_d; _d=d; *_d++=vars[N]; d=_d;}
    		      6          				
    			   \                                 In section .text, align 2, keep-with-next
    		      7          void f(unsigned long mask, void *d)
    		      8          {
    		      9            PROC(0,long,0);
    		   \                     f: (+1)
    		   \        0x0   0x....             LDR.N    R2,??DataTable1
    		   \        0x2   0x07C3             LSLS     R3,R0,#+31
    		   \        0x4   0xBF44             ITT      MI 
    		   \        0x6   0xF8D2 0xC000      LDRMI    R12,[R2, #+0]
    		   \        0xA   0xF841 0xCB04      STRMI    R12,[R1], #+4
    		     10            PROC(1,short,1);
    		   \        0xE   0x0783             LSLS     R3,R0,#+30
    		   \       0x10   0xBF44             ITT      MI 
    		   \       0x12   0xF8D2 0xC004      LDRMI    R12,[R2, #+4]
    		   \       0x16   0xF821 0xCB02      STRHMI   R12,[R1], #+2
    		     11            PROC(2,long,2);
    		   \       0x1A   0x0743             LSLS     R3,R0,#+29
    		   \       0x1C   0xBF44             ITT      MI 
    		   \       0x1E   0xF8D2 0xC008      LDRMI    R12,[R2, #+8]
    		   \       0x22   0xF841 0xCB04      STRMI    R12,[R1], #+4
    		     12            PROC(3,long,3);
    		   \       0x26   0x0703             LSLS     R3,R0,#+28
    		   \       0x28   0xBF44             ITT      MI 
    		   \       0x2A   0xF8D2 0xC00C      LDRMI    R12,[R2, #+12]
    		   \       0x2E   0xF841 0xCB04      STRMI    R12,[R1], #+4
    		     13            PROC(4,short,4);
    		   \       0x32   0x06C3             LSLS     R3,R0,#+27
    		   \       0x34   0xBF44             ITT      MI 
    		   \       0x36   0xF8D2 0xC010      LDRMI    R12,[R2, #+16]
    		   \       0x3A   0xF821 0xCB02      STRHMI   R12,[R1], #+2
    		     14            PROC(5,short,5);
    		   \       0x3E   0x0683             LSLS     R3,R0,#+26
    		   \       0x40   0xBF44             ITT      MI 
    		   \       0x42   0xF8D2 0xC014      LDRMI    R12,[R2, #+20]
    		   \       0x46   0xF821 0xCB02      STRHMI   R12,[R1], #+2
    		     15            PROC(6,long,6);
    		   \       0x4A   0x0643             LSLS     R3,R0,#+25
    		   \       0x4C   0xBF44             ITT      MI 
    		   \       0x4E   0xF8D2 0xC018      LDRMI    R12,[R2, #+24]
    		   \       0x52   0xF841 0xCB04      STRMI    R12,[R1], #+4
    		     16            PROC(7,short,7);
    		   \       0x56   0x0600             LSLS     R0,R0,#+24
    		   \       0x58   0xBF44             ITT      MI 
    		   \       0x5A   0x69D2             LDRMI    R2,[R2, #+28]
    		   \       0x5C   0x800A             STRHMI   R2,[R1, #+0]
    		     17          }
    		   \       0x5E   0x4770             BX       LR               ;; return
    		 				
    			

    Тут, конечно, может возникнуть вопрос другого характера. Например, если почти все параметры используются, то грузить их в регистры при помощи LDM будет малость эффективнее. А вот у IAR'а с использованием LDM как-то не сложилось, черт его знает, почему.

    Но возможен другой вариант. Допустим, что из всего списка в реальности надо вообще всего пару-тройку параметров генерить. Тогда куда более эффективным решением будет такое:

    	typedef void (*FillFunc)(void *, void *, long *);
    	 
    	#define GLUE(A,B) A##B
    	 
    	#define FillParam(T,N) \
    	void GLUE(FillParam,N)(void *functab, void *d, long *s) \
    	{ \
    	  T *_d; \
    	  _d=d; \
    	  *_d++=s[N]; \
    	  FillFunc *_functab=functab; \
    	  FillFunc nf=*_functab++; \
    	  nf(_functab,_d,s); \
    	}
    	 
    	FillParam(long,0)
    	FillParam(short,1)
    	FillParam(long,2)
    	FillParam(short,3)
    	 
    	void FillParamEnd(void *functab, void *d, long *s)
    	{
    	}
    	 
    	FillFunc FillerTask[]=
    	{
    	  FillParam0,FillParam1,FillParam2,FillParam3,
    	  FillParamEnd
    	};
    	 
    	void FillParamBegin(void *d, long *s)
    	{
    	  FillFunc *functab=FillerTask;
    	  FillFunc nf=*functab++;
    	  nf((void*)functab,d,s);
    	}
    	

    Результат как на асме:

    Spoiler

    				
    			     19          typedef void (*FillFunc)(void *, void *, long *);
    		     20          
    		     21          #define GLUE(A,B) A##B
    		     22          
    		     23          #define FillParam(T,N) \
    		     24          void GLUE(FillParam,N)(void *functab, void *d, long *s) \
    		     25          { \
    		     26            T *_d; \
    		     27            _d=d; \
    		     28            *_d++=s[N]; \
    		     29            FillFunc *_functab=functab; \
    		     30            FillFunc nf=*_functab++; \
    		     31            nf(_functab,_d,s); \
    		     32          }
    		     33          				
    			   \                                 In section .text, align 2, keep-with-next
    		     34          FillParam(long,0)
    		   \                     FillParam0: (+1)
    		   \        0x0   0x6813             LDR      R3,[R2, #+0]
    		   \        0x2   0xF841 0x3B04      STR      R3,[R1], #+4
    		   \        0x6   0xF850 0x3B04      LDR      R3,[R0], #+4
    		   \        0xA   0x4718             BX       R3				
    			   \                                 In section .text, align 2, keep-with-next
    		     35          FillParam(short,1)
    		   \                     FillParam1: (+1)
    		   \        0x0   0x6853             LDR      R3,[R2, #+4]
    		   \        0x2   0xF821 0x3B02      STRH     R3,[R1], #+2
    		   \        0x6   0xF850 0x3B04      LDR      R3,[R0], #+4
    		   \        0xA   0x4718             BX       R3				
    			   \                                 In section .text, align 2, keep-with-next
    		     36          FillParam(long,2)
    		   \                     FillParam2: (+1)
    		   \        0x0   0x6893             LDR      R3,[R2, #+8]
    		   \        0x2   0xF841 0x3B04      STR      R3,[R1], #+4
    		   \        0x6   0xF850 0x3B04      LDR      R3,[R0], #+4
    		   \        0xA   0x4718             BX       R3				
    			   \                                 In section .text, align 2, keep-with-next
    		     37          FillParam(short,3)
    		   \                     FillParam3: (+1)
    		   \        0x0   0x68D3             LDR      R3,[R2, #+12]
    		   \        0x2   0xF821 0x3B02      STRH     R3,[R1], #+2
    		   \        0x6   0xF850 0x3B04      LDR      R3,[R0], #+4
    		   \        0xA   0x4718             BX       R3
    		     38          				
    			   \                                 In section .text, align 2, keep-with-next
    		     39          void FillParamEnd(void *functab, void *d, long *s)
    		     40          {
    		     41          }
    		   \                     FillParamEnd: (+1)
    		   \        0x0   0x4770             BX       LR               ;; return
    		     42          				
    			   \                                 In section .data, align 4
    		     43          FillFunc FillerTask[]=
    		   \                     FillerTask:
    		   \        0x0   0x....'....        DC32 FillParam0, FillParam1, FillParam2, FillParam3, FillParamEnd
    		   \              0x....'....  
    		   \              0x....'....  
    		   \              0x....'....  
    		   \              0x....'....  
    		     44          {
    		     45            FillParam0,FillParam1,FillParam2,FillParam3,
    		     46            FillParamEnd
    		     47          };
    		     48          				
    			   \                                 In section .text, align 2, keep-with-next
    		     49          void FillParamBegin(void *d, long *s)
    		     50          {
    		   \                     FillParamBegin: (+1)
    		   \        0x0   0x460A             MOV      R2,R1
    		     51            FillFunc *functab=FillerTask;
    		     52            FillFunc nf=*functab++;
    		     53            nf((void*)functab,d,s);
    		   \        0x2   0x....             LDR.N    R3,??DataTable1_1
    		   \        0x4   0x4601             MOV      R1,R0
    		   \        0x6   0x1D18             ADDS     R0,R3,#+4
    		   \        0x8   0x681B             LDR      R3,[R3, #+0]
    		   \        0xA   0x4718             BX       R3
    		     54          }
    		 				
    			

    Естественно, FillerTask можно сгенерить с нужной Вам периодичностью из редко изменяемой маски.

     

    Ну и, конечно, возможна вообще циничная генерация самомодифицирующегося кода из команд LDR R2,[R0,#+disp] и STR(H) R2,[R1],#4(2). Его генерация отлично на Си пишется. И как бы не смешно это звучало, но это будет самый оптимальный вариант (ну, правда, максимум может понадобится 64*6+2=386 байт ОЗУ для хранения генерируемого кода.

  10. 7 hours ago, Politeh said:

    1. Должна быть

    Простите, кто кому что должен? Тут так не принято, тут помогают на добровольной основе. Либо Вы 

    1. можете собрать такой материал и выложить его в общий доступ на добровольной основе.

    2. можете задавать прямые вопросы в отдельных темах и получать на них ответы "гуру" на добровольной основе. 

    3. можете заплатить профессионалам, они сделают для Вас "дорожную карту" по борьбе за ЭМС. Заплатить, конечно, на добровольной основе.

  11. 10 hours ago, haker_fox said:

    А реально ли для синтеза использовать Cortex-M4F или такие вещи нужно делать на ЦСП? И если нужен сигнальный процессор, то на какие модели смотреть, ибо я в них не копенгаген) И да, это интерес чисто личный, не коммерческий, поэтому вопрос цены и эффективности пока не стоит...

    Вот тот самый Pianoteq есть для Linux под ARM, работает на Raspberry Pi. Это, конечно, не M4F, но таки ARM ;)

  12. Есть и чисто софтовые. Имеется в виду в виде VSTi.

    Есть, например, Pianoteq (https://www.modartt.com/), довольно давно его уже пилят. Это рояль моделирующий. Правда, вроде там самые атаки именно семплами сделаны, но сустейн именно моделирование.

     

    А еще есть ребята Audio Modeling SWAM (https://audiomodeling.com/). Там столько параметров, что приходится специальные контроллеры использовать для прописывания партий, одной клавиатурой (имеется в виду MIDI-клавиатура) не обойдешься:

    Некоторые целую струнную группу БСО ухитрились вот так прописать

    Только не спрашивайте, как и что там сделано, не дизассемблировал ;)

  13. Moderator: Пусть повисит тема немного, а потом снесем. Я бы сразу ее в оффтопик перенес, но тогда ТС утратит возможность доступа к теме.

  14. 23 minutes ago, iiv said:

    Технический репорт пишу с описанием того, что делаю.

    Я имею в виду к какой области относится Ваше изобретение или что там. Для чего применяется? Одно дело - несущую в телеграфном передатчике умножать, а другое - музыку питчшифтить.

  15. 36 minutes ago, iiv said:

    Мне же нужно, чтобы исходный сигнал был какой есть (обычно там множество различных частот), и этот умножитель действует на все частоты с одинаковым коэффициентом...

    В области обработки аудио-сигналов есть такой термин, как pitch shift. Тоже самое, но с другого боку (оставить частоты теми же, а изменить длительность) - это time stretching. Вам в каком вообще контексте термин нужен?

  16. 21 hours ago, SVNKz said:

    Попробуйте вариант проверки линейно нарастающим напряжением, треугольным, с выхода ЦАП, проверить его можно путём измерения ступенек напряжения на выходе высокоточным вольтметром.

     Вариант проверки чего? АЦП? Вы шутите? Там 120дБ ДД. С выхода какого ЦАП предлагаете взять такую пилу? И каким "высокоточным" вольтметром измерить ее "ступеньки"? 6 знаков минимум надо, а лучше бы 7.

    И да, там ухудшаются характеристики на постоянном токе. Полоса ниже 20Гц в аудио-применениях не волнует от слова совсем.

  17. 29 minutes ago, jcxz said:

    Это так можно только если действительно можно не записывать старшие 16 бит. Я выше уже писал об этом.

    Я так думаю, что если сдуру там и сделано 32 бита только, то можно писать не 0 и 0xFFFF, а 0 и 0xFFFFFFFF почти наверняка.

  18. Самый быстрый способ могу предложить только такой:

    	SBFX   R1,R0,#0,#1
    	STRH   R1,[R2,#0]   
    	SBFX   R1,R0,#1,#1
    	STRH   R1,[R2,#2]
    	....
    	SBFX   R1,R0,#7,#1
    	STRH   R1,[R2,#14]
    	

    По два такта на пиксель.

    Это вполне и при помощи GCC inline asm делается, так что можно обойтись без отдельного модуля на ассемблере.

×
×
  • Создать...