Корзина

0  Товары

0.00 RUB

Вход

Классический вход

Сообщество

Блог

Немного психоделики :)

Совершенно случайно, на просторах интернета был запеленгован блог товарища Arlet`а. В данном блоге меня заинтересовала генерация с помощью FPGA динамических, вращающихся плоскостей. Эффект достаточно интересный, в оригинале тип эффекта управляется с помощью переключателей. У нас никаких переключателей нет, поэтому мы будем управлять всем происходящим с помощью нашего ARM контроллера по USB. Для этого изменим код нашей статьи Первый проект для VE-EP4CE10E. Если в первом примере по нажатию кнопки '1' в USB терминале pin B.12 сбрасывался в состояние логического нуля, а по нажатию клавиши '2' устанавливался в состояние логической единицы, то теперь нам нужно сделать управление по четырем линиям. Для этого изменим код файла "main.c":

C++ Code:
  1. /* USER CODE BEGIN PV */
  2. unsigned char rx_buff[64];
  3. unsigned char tx_buff[64];
  4. unsigned char data0, data1, data2, data3;
  5. /* USER CODE END PV */

Создаем четыре переменные data0-data3 для контроля выводов нашего контроллера. Вы наверное зададитесь законным вопросом, а почему тип переменных не bool? Ответ, в принципе, достаточно прост: разрешение нашего файла .c- это значит что содержимое файла будет компилироваться C компилятором, а он (в отличие от C++) не поддерживает тип данных bool. Ну это было лирическое отступление. Приступим к управлению нашими эффектами, добавляем код:

C++ Code:
  1. /* USER CODE BEGIN 3 */
  2. if (VCP_read(&rx_buff, 1) != 1)
  3. continue;
  4. VCP_write("\r\nYou typed ", 12);
  5. VCP_write(&rx_buff, 1);
  6. VCP_write("\r\n", 2);
  7. if(rx_buff[0]=='1')
  8. {
  9. if(data0==0){data0=1;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, 1);} //MCU_DATA0=1
  10. else{data0=0;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, 0);} //MCU_DATA0=0
  11. }
  12. if(rx_buff[0]=='2')
  13. {
  14. if(data1==0){data1=1;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 1);} //MCU_DATA1=1
  15. else{data1=0;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, 0);} //MCU_DATA1=0
  16. }
  17. if(rx_buff[0]=='3')
  18. {
  19. if(data2==0){data2=1;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 1);} //MCU_DATA2=1
  20. else{data2=0;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, 0);} //MCU_DATA2=0
  21. }
  22. if(rx_buff[0]=='4')
  23. {
  24. if(data3==0){data3=1;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, 1);} //MCU_DATA3=1
  25. else{data3=0;HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, 0);} //MCU_DATA3=0
  26. }
  27. }
  28. /* USER CODE END 3 */

Теперь нажатие клавиши '1' управляет включение/выключением ноги B.12, клавиша '2' - B.13, клавиша '3' - B.14, клавиша '4' - B.15.

 В Quartus создаем новый проект. Основной файл графического ввода:

7ead6760f92f6a5aeb0da30ccdf37fe6.jpg

Распределение пинов:

f9db7dac8c87ac42b9b86b1ed07ecd40.jpg

Основной файл Verilog:

Verilog Code:
  1. /*
  2.  * main module for VGA demo.
  3.  *
  4.  * (C) Arlet Ottens
  5.  */
  6. module main( Clk, Reset, R, G, B, VSync, HSync, SW0, SW1, SW2 );
  7.  
  8. input Clk;
  9. input Reset;
  10.  
  11. // VGA
  12. output R;
  13. output G;
  14. output B;
  15. output VSync;
  16. output HSync;
  17.  
  18. // Switches
  19. input SW0;
  20. input SW1;
  21. input SW2;
  22.  
  23. // definitions
  24. reg R;
  25. reg G;
  26. reg B;
  27. reg VSync;
  28. reg HSync;
  29.  
  30. wire HSync0;
  31. wire VSync0;
  32. wire [9:0] Col;
  33. wire [8:0] Row;
  34. wire Col0;
  35. wire Row0;
  36. wire screen_active;
  37. wire PixelClock;
  38.  
  39.  
  40. vga vga( .Reset(Reset),
  41. .HSync(HSync0),
  42. .VSync(VSync0),
  43. .Clk50(Clk),
  44. .PClk(PixelClock),
  45. .Col(Col),
  46. .Row(Row),
  47. .Col0(Col0),
  48. .Row0(Row0),
  49. .Active(screen_active) );
  50.  
  51. reg [17:0] X0, Y0, X1, Y1, XI;
  52. reg [17:0] RX0, RY0, RX1, RY1;
  53. reg [17:0] GX0, GY0, GX1, GY1;
  54. reg signed [17:0] DY, DX;
  55. reg signed [17:0] RDY, RDX;
  56. reg signed [17:0] GDY, GDX;
  57. reg do_DY;
  58.  
  59. /*
  60.  * Rotation per line/frame depending on SW2
  61.  */
  62.  
  63. wire Rot = SW2 ? Row0 : Col0;
  64.  
  65. /*
  66.  * maintain transformation parameters
  67.  */
  68. always @(posedge Clk) begin
  69. if( Reset ) begin
  70. DY <= 2000;
  71. DX <= 2000;
  72. do_DY <= 0;
  73. end else if( Rot ) begin
  74. DY <= DY - (DX >>> 8);
  75. do_DY <= 1;
  76. end else if( do_DY ) begin
  77. DX <= DX + (DY >>> 8);
  78. do_DY <= 0;
  79. end
  80.  
  81. if( Reset ) begin
  82. RDY <= 2050;
  83. RDX <= 1950;
  84. end else if( Rot ) begin
  85. RDY <= RDY - (RDX >>> 8);
  86. end else if( do_DY ) begin
  87. RDX <= RDX + (RDY >>> 8);
  88. end
  89.  
  90. if( Reset ) begin
  91. GDY <= 2000;
  92. GDX <= 2000;
  93. end else if( Rot ) begin
  94. GDY <= GDY - (GDX >>> 8);
  95. end else if( do_DY ) begin
  96. GDX <= GDX + (GDY >>> 8);
  97. end
  98. end
  99.  
  100. /*
  101.  * calculate per-pixel mapping (based on rotozoom). Multipliers can be
  102.  * avoided by more clever code, but the Spartan-3 has plenty for this
  103.  * purpose.
  104.  */
  105. always @(posedge Clk) begin
  106. if( PixelClock ) begin
  107. if( Row0 ) begin
  108. X0 <= -DX * 18'd319;
  109. Y0 <= DY * 18'd241;
  110. X1 <= -DX * 18'd319;
  111. Y1 <= DY * 18'd241;
  112. end else if( Col0 ) begin
  113. X0 <= X1 + DY;
  114. Y0 <= Y1 - DX;
  115. X1 <= X1 + DY;
  116. Y1 <= Y1 - DX;
  117. end else begin
  118. X0 <= X0 + DX;
  119. Y0 <= Y0 + DY;
  120. end
  121.  
  122. if( Row0 ) begin
  123. RX0 <= -RDX * 18'd319;
  124. RY0 <= RDY * 18'd231;
  125. RX1 <= -RDX * 18'd319;
  126. RY1 <= RDY * 18'd237;
  127. end else if( Col0 ) begin
  128. RX0 <= RX1 + RDY;
  129. RY0 <= RY1 - RDX;
  130. RX1 <= RX1 + RDY;
  131. RY1 <= RY1 - RDX;
  132. end else begin
  133. RX0 <= RX0 + RDX;
  134. RY0 <= RY0 + RDY;
  135. end
  136.  
  137. if( Row0 ) begin
  138. GX0 <= -GDX * 18'd300;
  139. GY0 <= GDY * 18'd221;
  140. GX1 <= -GDX * 18'd300;
  141. GY1 <= GDY * 18'd221;
  142. end else if( Col0 ) begin
  143. GX0 <= GX1 + GDY;
  144. GY0 <= GY1 - GDX;
  145. GX1 <= GX1 + GDY;
  146. GY1 <= GY1 - GDX;
  147. end else begin
  148. GX0 <= GX0 + GDX;
  149. GY0 <= GY0 + GDY;
  150. end
  151. end
  152. end
  153.  
  154. /*
  155.  * select bits to XOR based on SW0
  156.  */
  157. wire [17:0] SRX1 = SW0 ? RX0 : RX0 << 1;
  158. wire [17:0] SGX1 = SW0 ? GX0 : GX0 << 1;
  159. wire [17:0] SX1 = SW0 ? X0 : X0 << 1;
  160.  
  161. wire [17:0] SRY1 = SW0 ? RY0 : RY0 << 1;
  162. wire [17:0] SGY1 = SW0 ? GY0 : GY0 << 1;
  163. wire [17:0] SY1 = SW0 ? Y0 : Y0 << 1;
  164.  
  165. /*
  166.  * select squares or lines based on SW1
  167.  */
  168. wire RB = SW1 ? (SRX1[17] ^ SRY1[17]) : SRX1[17];
  169. wire GB = SW1 ? (SGX1[17] ^ SGY1[17]) : SGX1[17];
  170. wire BB = SW1 ? ( SX1[17] ^ SY1[17]) : SX1[17];
  171.  
  172. /*
  173.  * output HSync/VSync and RGB data
  174.  */
  175. always @(posedge Clk) begin
  176. HSync <= HSync0;
  177. VSync <= VSync0;
  178. if( screen_active ) begin
  179. R <= ~BB & (RB | (GB & ~RB));
  180. G <= GB & ~BB & ~RB;
  181. B <= BB;
  182. end else begin
  183. B <= 0;
  184. G <= 0;
  185. R <= 0;
  186. end
  187. end
  188.  
  189. endmodule

Файл генератор VGA развертки:

Verilog Code:
  1. /*
  2.  * VGA timing generator
  3.  *
  4.  * (C) Arlet Ottens
  5.  */
  6.  
  7. module vga( Reset, VSync, HSync, Clk50, PClk, Row, Col, Row0, Col0, Active );
  8. input Reset;
  9. output VSync;
  10. output HSync;
  11. input Clk50;
  12.  
  13. // outputs to data generator
  14. output PClk; // pixel clock
  15. output Row0; // pulse when Row == 0
  16. output Col0; // pulse when Col == 0
  17. output [9:0] Col; // next column
  18. output [8:0] Row; // next row
  19. output Active; //
  20.  
  21. reg PClk; // pixel clock
  22. reg Row0; // pulse when Row == 0
  23. reg Col0; // pulse when Col == 0
  24. reg [12:0] HClock;
  25. reg [11:0] VClock;
  26. assign Col = HClock[9:0];
  27. assign Row = VClock[8:0];
  28. assign Active = HClock[11] & VClock[10];
  29. assign VSync = VClock[9];
  30. assign HSync = HClock[10];
  31.  
  32. /*
  33.  * VGA timing information.
  34.  */
  35. parameter
  36. HSYNC = 10'd95,
  37. HBACK = 10'd47,
  38. HACTIVE = 10'd639,
  39. HFRONT = 10'd15;
  40.  
  41. parameter
  42. VSYNC = 9'd1,
  43. VBACK = 9'd28,
  44. VACTIVE = 9'd479,
  45. VFRONT = 9'd9;
  46.  
  47. wire HStart = ( HClock == {3'b101, HBACK} );
  48. wire VStart = ( VClock == {3'b101, VBACK} );
  49.  
  50. /*
  51.  * make 25 MHz pixelclock
  52.  */
  53. always @(posedge Clk50)
  54. PClk <= Reset ? 0 : ~PClk;
  55.  
  56. /*
  57.  * Horizontal timing state machine
  58.  */
  59. always @(posedge Clk50) begin
  60. if( Reset ) begin
  61. HClock <= 0;
  62. Col0 <= 0;
  63. end else if( PClk ) begin
  64. casex( HClock )
  65. { 3'bxx0, HSYNC } : HClock <= { 3'b101, 10'd0 };
  66. { 3'b101, HBACK } : HClock <= { 3'b011, 10'd0 };
  67. { 3'bx11, HACTIVE } : HClock <= { 3'b001, 10'd0 };
  68. { 3'b001, HFRONT } : HClock <= { 3'b100, 10'd0 };
  69.  
  70. default:
  71. HClock <= { HClock[12:10], HClock[9:0] + 10'd1 };
  72. endcase
  73. end
  74. Col0 <= HStart;
  75. end
  76.  
  77. /*
  78.  * Vertical timing state machine
  79.  */
  80. always @(posedge Clk50) begin
  81. if( Reset ) begin
  82. VClock <= 0;
  83. Row0 <= 0;
  84. end else if( PClk & HStart ) begin
  85. casex ( VClock )
  86. { 3'bxx0, VSYNC } : VClock <= { 3'b101, 9'd0 };
  87. { 3'b101, VBACK } : VClock <= { 3'b011, 9'd0 };
  88. { 3'bx11, VACTIVE } : VClock <= { 3'b001, 9'd0 };
  89. { 3'b001, VFRONT } : VClock <= { 3'b100, 9'd0 };
  90.  
  91. default:
  92. VClock <= { VClock[11:9], VClock[8:0] + 9'd1};
  93. endcase
  94. end
  95. Row0 <= HStart & VStart;
  96. end
  97.  
  98. endmodul

Исходный код для FPGA: vga_demo.zip

Всех с наступающим ДНЕМ РАДИО и ДНЕМ ПОБЕДЫ!

Карта сайта Визуальная электроника Полезные ссылки сайта Визуальная электроника

Алиса это умеет

Оплата товаров

Cookies make it easier for us to provide you with our services. With the usage of our services you permit us to use cookies.
More information Ok