Add FPGA-driven video using PIO/DMA
This commit is contained in:
parent
1ca3d882a7
commit
b725311229
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
build/
|
||||
.idea/
|
||||
ice/mandelbrot/impl_1/
|
||||
|
@ -8,9 +8,12 @@ pico_sdk_init()
|
||||
add_subdirectory(pico-ice-sdk)
|
||||
|
||||
add_executable(pico-ice-video main.cpp usb_descriptors.c)
|
||||
|
||||
pico_generate_pio_header(pico-ice-video ${CMAKE_CURRENT_LIST_DIR}/fpga.pio)
|
||||
|
||||
target_link_libraries(pico-ice-video pico_ice_sdk pico_ice_usb pico_stdio_usb pico_bootsel_via_double_reset)
|
||||
target_include_directories(pico-ice-video PUBLIC ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_BINARY_DIR})
|
||||
|
||||
pico_add_extra_outputs(pico-ice-video)
|
||||
pico_enable_stdio_usb(pico-ice-video 0)
|
||||
pico_enable_stdio_usb(pico-ice-video 1)
|
||||
pico_enable_stdio_uart(pico-ice-video 0)
|
57
fpga.pio
Normal file
57
fpga.pio
Normal file
@ -0,0 +1,57 @@
|
||||
.pio_version 0
|
||||
|
||||
.program fpga
|
||||
.fifo rx
|
||||
|
||||
set x, 8
|
||||
|
||||
.wrap_target
|
||||
|
||||
in x, 4
|
||||
in null, 4
|
||||
push
|
||||
|
||||
in pins, 8 [1]
|
||||
push
|
||||
|
||||
in x, 4
|
||||
in null, 4
|
||||
push
|
||||
|
||||
in pins, 8 [1]
|
||||
push
|
||||
|
||||
.wrap
|
||||
|
||||
% c-sdk {
|
||||
#include <hardware/dma.h>
|
||||
|
||||
#ifndef DMA_CHANNEL
|
||||
#define DMA_CHANNEL 0
|
||||
#endif//DMA_CHANNEL
|
||||
|
||||
static uint8_t frame_buffer[2][FRAME_WIDTH * FRAME_HEIGHT * 16 / 8] = { };
|
||||
static bool current_frame = false;
|
||||
|
||||
static inline void fpga_program_init(PIO pio, uint sm, uint offset, uint pin_base, float div)
|
||||
{
|
||||
{
|
||||
pio_sm_config c = fpga_program_get_default_config(offset);
|
||||
sm_config_set_in_pins(&c, pin_base);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin_base, 8, false);
|
||||
|
||||
sm_config_set_in_shift(&c, false, false, 8);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
}
|
||||
{
|
||||
dma_channel_config c = dma_channel_get_default_config(DMA_CHANNEL);
|
||||
channel_config_set_read_increment(&c, false);
|
||||
channel_config_set_write_increment(&c, true);
|
||||
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
|
||||
channel_config_set_dreq(&c, pio_get_dreq(pio, sm, false));
|
||||
|
||||
dma_channel_configure(DMA_CHANNEL, &c, NULL, &pio->rxf[sm], FRAME_WIDTH * FRAME_HEIGHT * 2 + 1, false);
|
||||
}
|
||||
}
|
||||
%}
|
11
ice/constraints.pdc
Normal file
11
ice/constraints.pdc
Normal file
@ -0,0 +1,11 @@
|
||||
ldc_set_location -site 35 [get_ports {clk}]
|
||||
ldc_set_location -site 14 [get_ports {start}]
|
||||
|
||||
ldc_set_location -site 27 [get_ports {data[0]}]
|
||||
ldc_set_location -site 25 [get_ports {data[1]}]
|
||||
ldc_set_location -site 21 [get_ports {data[2]}]
|
||||
ldc_set_location -site 19 [get_ports {data[3]}]
|
||||
ldc_set_location -site 26 [get_ports {data[4]}]
|
||||
ldc_set_location -site 23 [get_ports {data[5]}]
|
||||
ldc_set_location -site 20 [get_ports {data[6]}]
|
||||
ldc_set_location -site 18 [get_ports {data[7]}]
|
1
ice/constraints.sdc
Normal file
1
ice/constraints.sdc
Normal file
@ -0,0 +1 @@
|
||||
create_clock -period 20.8333 [get_ports {clk}]
|
17
ice/mandelbrot/.recovery
Normal file
17
ice/mandelbrot/.recovery
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RadiantProject version="4.2" radiant="2024.1.0.34.2" title="mandelbrot" device="iCE40UP5K-SG48I" performance_grade="High-Performance_1.2V" family_int="ice40tp" device_int="itpa08" package_int="SG48" operation_int="IND" speed_int="6" default_implementation="impl_1">
|
||||
<Options/>
|
||||
<Implementation title="impl_1" dir="impl_1" description="impl_1" synthesis="synplify" default_strategy="Strategy1">
|
||||
<Options def_top="top"/>
|
||||
<Source name="source/impl_1/top.sv" type="Verilog" type_short="Verilog">
|
||||
<Options VerilogStandard="System Verilog" top_module="top"/>
|
||||
</Source>
|
||||
<Source name="../constraints.pdc" type="Physical Constraints File" type_short="PDC">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="../constraints.sdc" type="Pre-Synthesis Constraints File" type_short="SDC">
|
||||
<Options/>
|
||||
</Source>
|
||||
</Implementation>
|
||||
<Strategy name="Strategy1" file="mandelbrot1.sty"/>
|
||||
</RadiantProject>
|
6
ice/mandelbrot/drc.log
Normal file
6
ice/mandelbrot/drc.log
Normal file
@ -0,0 +1,6 @@
|
||||
DRC: Design Rule Check Radiant Software (64-bit) 2024.1.0.34.2
|
||||
Wed Sep 25 13:18:59 2024
|
||||
|
||||
WARNING <71003020> - Top module port 'start' does not connect to anything.
|
||||
ERROR <71003010> - The port [clk] is assigned to a nonexistent pin [35]. Reassign the port to a valid pin.
|
||||
ERROR <71003010> - The port [data[0]] is assigned to a nonexistent pin [27]. Reassign the port to a valid pin.
|
17
ice/mandelbrot/mandelbrot.rdf
Normal file
17
ice/mandelbrot/mandelbrot.rdf
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<RadiantProject version="4.2" radiant="2024.1.0.34.2" title="mandelbrot" device="iCE40UP5K-UWG30ITR" performance_grade="High-Performance_1.2V" family_int="ice40tp" device_int="itpa08" package_int="UWG30" operation_int="IND" speed_int="6" default_implementation="impl_1">
|
||||
<Options/>
|
||||
<Implementation title="impl_1" dir="impl_1" description="impl_1" synthesis="synplify" default_strategy="Strategy1">
|
||||
<Options/>
|
||||
<Source name="../top.sv" type="Verilog" type_short="Verilog">
|
||||
<Options VerilogStandard="System Verilog"/>
|
||||
</Source>
|
||||
<Source name="../constraints.pdc" type="Physical Constraints File" type_short="PDC">
|
||||
<Options/>
|
||||
</Source>
|
||||
<Source name="../constraints.sdc" type="Pre-Synthesis Constraints File" type_short="SDC">
|
||||
<Options/>
|
||||
</Source>
|
||||
</Implementation>
|
||||
<Strategy name="Strategy1" file="mandelbrot1.sty"/>
|
||||
</RadiantProject>
|
138
ice/mandelbrot/mandelbrot1.sty
Normal file
138
ice/mandelbrot/mandelbrot1.sty
Normal file
@ -0,0 +1,138 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE strategy>
|
||||
<Strategy version="1.0" predefined="0" description="" label="Strategy1">
|
||||
<Property name="PROP_BD_EdfHardtimer" value="Enable" time="0"/>
|
||||
<Property name="PROP_BD_EdfInBusNameConv" value="None" time="0"/>
|
||||
<Property name="PROP_BD_EdfInLibPath" value="" time="0"/>
|
||||
<Property name="PROP_BD_EdfInRemLoc" value="Off" time="0"/>
|
||||
<Property name="PROP_BD_EdfMemPath" value="" time="0"/>
|
||||
<Property name="PROP_BD_ParSearchPath" value="" time="0"/>
|
||||
<Property name="PROP_BIT_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_BIT_INITEBR0" value="True" time="0"/>
|
||||
<Property name="PROP_BIT_INITEBR1" value="True" time="0"/>
|
||||
<Property name="PROP_BIT_INITEBR2" value="True" time="0"/>
|
||||
<Property name="PROP_BIT_INITEBR3" value="True" time="0"/>
|
||||
<Property name="PROP_BIT_NVCMSecurity" value="False" time="0"/>
|
||||
<Property name="PROP_BIT_NoHeader" value="False" time="0"/>
|
||||
<Property name="PROP_BIT_NoPullup" value="False" time="0"/>
|
||||
<Property name="PROP_BIT_OSCFREQ" value="Slow" time="0"/>
|
||||
<Property name="PROP_BIT_OutFormatBitGen" value="bin" time="0"/>
|
||||
<Property name="PROP_BIT_RunDRCBitGen" value="True" time="0"/>
|
||||
<Property name="PROP_BIT_SPILowPower" value="False" time="0"/>
|
||||
<Property name="PROP_BIT_WarmBoot" value="False" time="0"/>
|
||||
<Property name="PROP_CPE_IPDebugMode" value="False" time="0"/>
|
||||
<Property name="PROP_IOTIMING_AllSpeed" value="False" time="0"/>
|
||||
<Property name="PROP_LST_AllowDUPMod" value="False" time="0"/>
|
||||
<Property name="PROP_LST_AllowMixedAssignments" value="False" time="0"/>
|
||||
<Property name="PROP_LST_CarryChain" value="True" time="0"/>
|
||||
<Property name="PROP_LST_CarryChainLength" value="0" time="0"/>
|
||||
<Property name="PROP_LST_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_LST_DSPStyle" value="DSP" time="0"/>
|
||||
<Property name="PROP_LST_DSPUtil" value="100" time="0"/>
|
||||
<Property name="PROP_LST_DecodeUnreachableStates" value="False" time="0"/>
|
||||
<Property name="PROP_LST_EBRUtil" value="100" time="0"/>
|
||||
<Property name="PROP_LST_EdfFrequency" value="200" time="0"/>
|
||||
<Property name="PROP_LST_EdfInLibPath" value="" time="0"/>
|
||||
<Property name="PROP_LST_EdfInRemLoc" value="Off" time="0"/>
|
||||
<Property name="PROP_LST_EdfMemPath" value="" time="0"/>
|
||||
<Property name="PROP_LST_FIXGATEDCLKS" value="True" time="0"/>
|
||||
<Property name="PROP_LST_FSMEncodeStyle" value="Auto" time="0"/>
|
||||
<Property name="PROP_LST_IOInsertion" value="True" time="0"/>
|
||||
<Property name="PROP_LST_IgnoreSDCError" value="False" time="0"/>
|
||||
<Property name="PROP_LST_InterFileDump" value="False" time="0"/>
|
||||
<Property name="PROP_LST_LoopLimit" value="1950" time="0"/>
|
||||
<Property name="PROP_LST_MaxFanout" value="1000" time="0"/>
|
||||
<Property name="PROP_LST_OptimizeGoal" value="Area" time="0"/>
|
||||
<Property name="PROP_LST_PropagatConst" value="True" time="0"/>
|
||||
<Property name="PROP_LST_RAMStyle" value="Auto" time="0"/>
|
||||
<Property name="PROP_LST_ROMStyle" value="Auto" time="0"/>
|
||||
<Property name="PROP_LST_RWCheckOnRam" value="False" time="0"/>
|
||||
<Property name="PROP_LST_RemoveDupRegs" value="True" time="0"/>
|
||||
<Property name="PROP_LST_ReportTrimmedUserNets" value="False" time="0"/>
|
||||
<Property name="PROP_LST_ResolvedMixedDrivers" value="False" time="0"/>
|
||||
<Property name="PROP_LST_ResourceShare" value="True" time="0"/>
|
||||
<Property name="PROP_LST_UseIOReg" value="Auto" time="0"/>
|
||||
<Property name="PROP_LST_VHDL2008" value="False" time="0"/>
|
||||
<Property name="PROP_MAPSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
||||
<Property name="PROP_MAPSTA_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_MAPSTA_EndPtNumber" value="10" time="0"/>
|
||||
<Property name="PROP_MAPSTA_NPerEnd" value="1" time="0"/>
|
||||
<Property name="PROP_MAPSTA_NumPathsPerClock" value="10" time="0"/>
|
||||
<Property name="PROP_MAPSTA_ReportFormat" value="Lattice Standard" time="0"/>
|
||||
<Property name="PROP_MAPSTA_SpeedForHoldAnalysis" value="m" time="0"/>
|
||||
<Property name="PROP_MAPSTA_SpeedForSetupAnalysis" value="default" time="0"/>
|
||||
<Property name="PROP_MAPSTA_UnconstrainedPathsNumber" value="10" time="0"/>
|
||||
<Property name="PROP_MAP_IgnoreSDCErr" value="False" time="0"/>
|
||||
<Property name="PROP_MAP_MapModArgs" value="" time="0"/>
|
||||
<Property name="PROP_MAP_SigCrossRef" value="False" time="0"/>
|
||||
<Property name="PROP_MAP_SymCrossRef" value="False" time="0"/>
|
||||
<Property name="PROP_PARSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
||||
<Property name="PROP_PARSTA_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_PARSTA_EndPtNumber" value="10" time="0"/>
|
||||
<Property name="PROP_PARSTA_NPerEnd" value="1" time="0"/>
|
||||
<Property name="PROP_PARSTA_NumPathsPerClock" value="10" time="0"/>
|
||||
<Property name="PROP_PARSTA_ReportFormat" value="Lattice Standard" time="0"/>
|
||||
<Property name="PROP_PARSTA_SpeedForHoldAnalysis" value="m" time="0"/>
|
||||
<Property name="PROP_PARSTA_SpeedForSetupAnalysis" value="default" time="0"/>
|
||||
<Property name="PROP_PARSTA_UnconstrainedPathsNumber" value="10" time="0"/>
|
||||
<Property name="PROP_PAR_DisableAutoHldTiming" value="False" time="0"/>
|
||||
<Property name="PROP_PAR_DisableTDParDes" value="False" time="0"/>
|
||||
<Property name="PROP_PAR_ImposeHoldTimeCorrect" value="False" time="0"/>
|
||||
<Property name="PROP_PAR_NumOfHostMachineCores" value="1" time="0"/>
|
||||
<Property name="PROP_PAR_PARModArgs" value="" time="0"/>
|
||||
<Property name="PROP_PAR_PackLogicUtil" value="" time="0"/>
|
||||
<Property name="PROP_PAR_ParMultiNodeList" value="" time="0"/>
|
||||
<Property name="PROP_PAR_ParRunPlaceOnly" value="False" time="0"/>
|
||||
<Property name="PROP_PAR_PlcIterParDes" value="1" time="0"/>
|
||||
<Property name="PROP_PAR_PlcStCostTblParDes" value="1" time="0"/>
|
||||
<Property name="PROP_PAR_PriHldCorrectOverSetup" value="False" time="0"/>
|
||||
<Property name="PROP_PAR_SaveBestRsltParDes" value="1" time="0"/>
|
||||
<Property name="PROP_PAR_SpdGradeHoldOpt" value="m" time="0"/>
|
||||
<Property name="PROP_PAR_SpdGradeSetupOpt" value="Default" time="0"/>
|
||||
<Property name="PROP_PAR_StopZero" value="False" time="0"/>
|
||||
<Property name="PROP_PAR_parPathBased" value="On" time="0"/>
|
||||
<Property name="PROP_POSTSYN_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_POSTSYN_ExtModuleFiles" value="" time="0"/>
|
||||
<Property name="PROP_POSTSYN_IgnoreSDCErr" value="False" time="0"/>
|
||||
<Property name="PROP_SYNSTA_AnalysisOption" value="Standard Setup and Hold Analysis" time="0"/>
|
||||
<Property name="PROP_SYNSTA_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_SYNSTA_EndPtNumber" value="10" time="0"/>
|
||||
<Property name="PROP_SYNSTA_NPerEnd" value="1" time="0"/>
|
||||
<Property name="PROP_SYNSTA_NumPathsPerClock" value="10" time="0"/>
|
||||
<Property name="PROP_SYNSTA_ReportFormat" value="Lattice Standard" time="0"/>
|
||||
<Property name="PROP_SYNSTA_UnconstrainedPathsNumber" value="10" time="0"/>
|
||||
<Property name="PROP_SYN_ClockConversion" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_CmdLineArgs" value="" time="0"/>
|
||||
<Property name="PROP_SYN_EdfAllowDUPMod" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_EdfArea" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_EdfArrangeVHDLFiles" value="True" time="0"/>
|
||||
<Property name="PROP_SYN_EdfDefEnumEncode" value="Default" time="0"/>
|
||||
<Property name="PROP_SYN_EdfFanout" value="1000" time="0"/>
|
||||
<Property name="PROP_SYN_EdfFrequency" value="200" time="0"/>
|
||||
<Property name="PROP_SYN_EdfInsertIO" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_EdfNumCritPath" value="" time="0"/>
|
||||
<Property name="PROP_SYN_EdfNumStartEnd" value="" time="0"/>
|
||||
<Property name="PROP_SYN_EdfOutNetForm" value="None" time="0"/>
|
||||
<Property name="PROP_SYN_EdfPushTirstates" value="True" time="0"/>
|
||||
<Property name="PROP_SYN_EdfResSharing" value="True" time="0"/>
|
||||
<Property name="PROP_SYN_EdfRunRetiming" value="Pipelining Only" time="0"/>
|
||||
<Property name="PROP_SYN_EdfSymFSM" value="True" time="0"/>
|
||||
<Property name="PROP_SYN_EdfUnconsClk" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_ExportSetting" value="Yes" time="0"/>
|
||||
<Property name="PROP_SYN_FDCFiles" value="" time="0"/>
|
||||
<Property name="PROP_SYN_LibPath" value="" time="0"/>
|
||||
<Property name="PROP_SYN_RamRWCheck" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_ResolvedMixedDrivers" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_ResynthesizeAll" value="True" time="0"/>
|
||||
<Property name="PROP_SYN_UpdateCompilePtTimData" value="False" time="0"/>
|
||||
<Property name="PROP_SYN_VHDL2008" value="False" time="0"/>
|
||||
<Property name="PROP_TIM_MaxDelSimDes" value="" time="0"/>
|
||||
<Property name="PROP_TIM_MinSpeedGrade" value="False" time="0"/>
|
||||
<Property name="PROP_TIM_ModPreSimDes" value="" time="0"/>
|
||||
<Property name="PROP_TIM_NegStupHldTim" value="True" time="0"/>
|
||||
<Property name="PROP_TIM_TimSimGenPUR" value="True" time="0"/>
|
||||
<Property name="PROP_TIM_TimSimGenX" value="False" time="0"/>
|
||||
<Property name="PROP_TIM_TimSimHierSep" value="" time="0"/>
|
||||
<Property name="PROP_TIM_TrgtSpeedGrade" value="High-Performance_1.2V" time="0"/>
|
||||
<Property name="PROP_TMCHK_EnableCheck" value="True" time="0"/>
|
||||
</Strategy>
|
97
ice/mandelbrot/mandelbrot_tcl.html
Normal file
97
ice/mandelbrot/mandelbrot_tcl.html
Normal file
@ -0,0 +1,97 @@
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>Lattice TCL Log</TITLE>
|
||||
<link href="file:///C:/lscc/radiant/2024.1/data/theme/css/light/report.css" rel="stylesheet" type="text/css" media="screen"/>
|
||||
<link href="file:///C:/lscc/radiant/2024.1/data/theme/css/print/report.css" rel="stylesheet" type="text/css" media="print"/>
|
||||
<style type="text/css">
|
||||
#toc {
|
||||
position: fixed;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
padding: 2px 5px 2px 5px;
|
||||
background-color:rgba(210,210,210,0.1);
|
||||
border-style: solid;
|
||||
border-color: rgba(192,192,192,0.8);
|
||||
border-width:1px;
|
||||
}
|
||||
#toc_list {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
function showTocList() {
|
||||
var a = document.getElementById("toc_list");
|
||||
a.style.display = "block";
|
||||
}
|
||||
|
||||
function hideTocList() {
|
||||
var a = document.getElementById("toc_list");
|
||||
if (a)
|
||||
a.style.display = "none";
|
||||
}
|
||||
|
||||
//-->
|
||||
</script>
|
||||
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
|
||||
<DIV id="content" onclick="hideTocList()"><PRE>
|
||||
</PRE></DIV>
|
||||
|
||||
<button id="back_to_top" class="radiant" onclick="scrollToTop()"><</button>
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
var scrollStep = 0;
|
||||
function scrollToTop(){
|
||||
var funScroll = function() {
|
||||
var top = document.body.scrollTop;
|
||||
if (top == 0) {
|
||||
scrollStep = 0;
|
||||
return;
|
||||
}
|
||||
if (scrollStep == 0)
|
||||
scrollStep = top/20 + 1;
|
||||
top -= scrollStep;
|
||||
if (top < 0)
|
||||
top = 0;
|
||||
document.body.scrollTop = top;
|
||||
requestAnimationFrame(funScroll);
|
||||
};
|
||||
funScroll();
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', function(e) {
|
||||
var backToTop = document.getElementById('back_to_top')
|
||||
if (document.body.scrollTop > 0) {
|
||||
backToTop.style.display = 'block';
|
||||
} else { backToTop.style.display = 'none' }});
|
||||
|
||||
//-->
|
||||
</script>
|
||||
|
||||
<style type="text/css">
|
||||
#back_to_top {
|
||||
bottom:20px; right:20px;
|
||||
width:30px; height:30px;
|
||||
font-size: 20px;
|
||||
padding: 2px 5px 2px 5px;
|
||||
position:fixed;
|
||||
background-color:rgba(210,210,210,0.1);
|
||||
border-style: solid;
|
||||
border-color: rgba(192,192,192,0.8);
|
||||
border-width:1px;
|
||||
display:none;
|
||||
-webkit-transform: rotate(90deg);
|
||||
-webkit-transform-origin:50% 50%;
|
||||
}
|
||||
#back_to_top:focus {
|
||||
outline-width:0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
</BODY>
|
||||
|
0
ice/mandelbrot/promote.pfl
Normal file
0
ice/mandelbrot/promote.pfl
Normal file
3
ice/mandelbrot/promote.xml
Normal file
3
ice/mandelbrot/promote.xml
Normal file
@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<userSetting name="C:/Users/fuzzc/Documents/Hardware/pico-ice/pico-ice-video/ice/mandelbrot/promote.xml" version="Diamond (64-bit) 2024.1.0.34.2" date="Thu Sep 26 10:20:19 2024" vendor="Lattice Semiconductor Corporation" >
|
||||
</userSetting>
|
20
ice/mandelbrot/source/impl_1/top.sv
Normal file
20
ice/mandelbrot/source/impl_1/top.sv
Normal file
@ -0,0 +1,20 @@
|
||||
module top
|
||||
(
|
||||
input wire clk,
|
||||
input wire start,
|
||||
output wire [7:0] data
|
||||
);
|
||||
|
||||
reg [7:0] data_r;
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
data_r <= data_r + 1;
|
||||
|
||||
if (data_r < 16 || data_r > 235) begin
|
||||
data_r <= 16;
|
||||
end
|
||||
end
|
||||
|
||||
assign data = data_r;
|
||||
|
||||
endmodule
|
8
ice/top.sv
Normal file
8
ice/top.sv
Normal file
@ -0,0 +1,8 @@
|
||||
module top
|
||||
(
|
||||
input wire clk,
|
||||
input wire start,
|
||||
output wire [7:0] data
|
||||
);
|
||||
|
||||
endmodule
|
115
main.cpp
115
main.cpp
@ -1,30 +1,73 @@
|
||||
#include <ice_fpga.h>
|
||||
#include <ice_led.h>
|
||||
#include <ice_usb.h>
|
||||
|
||||
#include <tusb.h>
|
||||
#include <boards/pico_ice.h>
|
||||
#include <bsp/board_api.h>
|
||||
|
||||
#include <pico/stdio.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/clocks.h>
|
||||
#include <hardware/uart.h>
|
||||
#include <pico/stdio.h>
|
||||
|
||||
#include "fpga.pio.h"
|
||||
|
||||
static PIO pio;
|
||||
static uint sm;
|
||||
|
||||
#define ICE_FPGA_START_FRAME_PIN ICE_FPGA_14_PIN
|
||||
|
||||
static void video_task();
|
||||
static void start_next_frame()
|
||||
{
|
||||
if (dma_channel_is_busy(DMA_CHANNEL)) { return; }
|
||||
|
||||
gpio_put(ICE_FPGA_START_FRAME_PIN, true);
|
||||
sleep_ms(10);
|
||||
printf("%d - ", gpio_get(ICE_FPGA_START_FRAME_PIN));
|
||||
gpio_put(ICE_FPGA_START_FRAME_PIN, false);
|
||||
sleep_ms(10);
|
||||
printf("%d - ", gpio_get(ICE_FPGA_START_FRAME_PIN));
|
||||
|
||||
pio_sm_set_enabled(pio, sm, false);
|
||||
pio_sm_clear_fifos(pio, sm);
|
||||
pio_sm_restart(pio, sm);
|
||||
dma_channel_set_write_addr(DMA_CHANNEL, frame_buffer[current_frame] - !current_frame, true);
|
||||
current_frame = !current_frame;
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
stdio_init_all();
|
||||
// set to 120 MHz as it's exactly 2.5x the FPGA clock
|
||||
set_sys_clock_khz(120000, true);
|
||||
|
||||
uart_init(uart0, 115200);
|
||||
gpio_set_function(0, GPIO_FUNC_UART);
|
||||
gpio_set_function(1, GPIO_FUNC_UART);
|
||||
tusb_init();
|
||||
stdio_init_all();
|
||||
|
||||
ice_led_init();
|
||||
ice_usb_init();
|
||||
|
||||
ice_fpga_init(12);
|
||||
ice_fpga_init(48);
|
||||
ice_fpga_start();
|
||||
|
||||
gpio_init_mask(0b111111111);
|
||||
gpio_set_dir(ICE_FPGA_27_PIN, GPIO_IN); // 0
|
||||
gpio_set_dir(ICE_FPGA_25_PIN, GPIO_IN); // 1
|
||||
gpio_set_dir(ICE_FPGA_21_PIN, GPIO_IN); // 2
|
||||
gpio_set_dir(ICE_FPGA_19_PIN, GPIO_IN); // 3
|
||||
gpio_set_dir(ICE_FPGA_26_PIN, GPIO_IN); // 4
|
||||
gpio_set_dir(ICE_FPGA_23_PIN, GPIO_IN); // 5
|
||||
gpio_set_dir(ICE_FPGA_20_PIN, GPIO_IN); // 6
|
||||
gpio_set_dir(ICE_FPGA_18_PIN, GPIO_IN); // 7
|
||||
|
||||
gpio_set_dir(ICE_FPGA_START_FRAME_PIN, GPIO_OUT); // 8
|
||||
|
||||
gpio_put(ICE_FPGA_START_FRAME_PIN, false);
|
||||
|
||||
pio = pio0;
|
||||
const uint offset = pio_add_program(pio, &fpga_program);
|
||||
sm = pio_claim_unused_sm(pio, true);
|
||||
fpga_program_init(pio, sm, offset, 0, 1);
|
||||
|
||||
tud_init(0);
|
||||
|
||||
if (board_init_after_tusb)
|
||||
@ -41,60 +84,16 @@ int main()
|
||||
}
|
||||
|
||||
static unsigned int interval_ms = 1000 / FRAME_RATE;
|
||||
static unsigned int frame_num = 0;
|
||||
static bool tx_busy = false;
|
||||
|
||||
static uint8_t frame_buffer[FRAME_WIDTH * FRAME_HEIGHT * 16 / 8] = { };
|
||||
|
||||
static void fill_color_bar(uint8_t* buffer, const unsigned int start_position)
|
||||
{
|
||||
static constexpr uint8_t bar_color[8][4] =
|
||||
{
|
||||
/* Y, U, Y, V */
|
||||
{ 235, 128, 235, 128 }, /* 100% White */
|
||||
{ 219, 16, 219, 138 }, /* Yellow */
|
||||
{ 188, 154, 188, 16 }, /* Cyan */
|
||||
{ 173, 42, 173, 26 }, /* Green */
|
||||
{ 78, 214, 78, 230 }, /* Magenta */
|
||||
{ 63, 102, 63, 240 }, /* Red */
|
||||
{ 32, 240, 32, 118 }, /* Blue */
|
||||
{ 16, 128, 16, 128 }, /* Black */
|
||||
};
|
||||
|
||||
uint8_t* p;
|
||||
|
||||
const uint8_t* end = &buffer[FRAME_WIDTH * 2];
|
||||
const unsigned int index = (FRAME_WIDTH / 2 - 1) - (start_position % (FRAME_WIDTH / 2));
|
||||
|
||||
p = &buffer[index * 4];
|
||||
for (unsigned int i = 0; i < 8; i++)
|
||||
{
|
||||
for (int j = 0; j < FRAME_WIDTH / (2 * 8); j++)
|
||||
{
|
||||
memcpy(p, &bar_color[i], 4);
|
||||
p += 4;
|
||||
if (p >= end) { p = buffer; }
|
||||
}
|
||||
}
|
||||
|
||||
p = &buffer[FRAME_WIDTH * 2];
|
||||
for (unsigned int i = 1; i < FRAME_HEIGHT; i++)
|
||||
{
|
||||
memcpy(p, buffer, FRAME_WIDTH * 2);
|
||||
p += FRAME_WIDTH * 2;
|
||||
}
|
||||
}
|
||||
|
||||
void video_task()
|
||||
{
|
||||
static bool already_sent = false;
|
||||
static unsigned int start_ms = 0;
|
||||
|
||||
// don't send data if not streaming
|
||||
if (!tud_video_n_streaming(0, 0))
|
||||
{
|
||||
already_sent = false;
|
||||
frame_num = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -104,9 +103,8 @@ void video_task()
|
||||
tx_busy = true;
|
||||
start_ms = board_millis();
|
||||
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
|
||||
tud_video_n_frame_xfer(0, 0, frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
start_next_frame();
|
||||
tud_video_n_frame_xfer(0, 0, frame_buffer[current_frame], FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
}
|
||||
|
||||
const unsigned int cur = board_millis();
|
||||
@ -115,15 +113,14 @@ void video_task()
|
||||
start_ms += interval_ms;
|
||||
tx_busy = true;
|
||||
|
||||
fill_color_bar(frame_buffer, frame_num);
|
||||
tud_video_n_frame_xfer(0, 0, frame_buffer, FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
tud_video_n_frame_xfer(0, 0, frame_buffer[current_frame], FRAME_WIDTH * FRAME_HEIGHT * 16 / 8);
|
||||
}
|
||||
|
||||
void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx)
|
||||
{
|
||||
tx_busy = false;
|
||||
|
||||
frame_num++;
|
||||
start_next_frame();
|
||||
}
|
||||
|
||||
int tud_video_commit_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, const video_probe_and_commit_control_t* parameters)
|
||||
|
@ -69,11 +69,11 @@
|
||||
// Must be a multiple of flash page size
|
||||
#define CFG_TUD_DFU_XFER_BUFSIZE 256
|
||||
|
||||
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 256
|
||||
#define CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE 1023
|
||||
#define CFG_TUD_VIDEO_STREAMING_BULK 0
|
||||
|
||||
#define FRAME_WIDTH 32
|
||||
#define FRAME_HEIGHT 18
|
||||
#define FRAME_WIDTH 320
|
||||
#define FRAME_HEIGHT 180
|
||||
#define FRAME_RATE 60
|
||||
|
||||
// Temporarily here until ice_usb.h has necessary info
|
||||
|
Loading…
Reference in New Issue
Block a user