├── .gitmodules ├── LICENSE ├── README.md ├── bitstreams ├── README.md ├── boot.bin ├── fpga_hdmi.bit ├── fpga_hdmi_720p.bit └── fpga_vga.bit ├── docs ├── arty.png ├── block_diagram.png ├── demo.png └── ir_conn.png ├── firmware ├── README.md ├── app │ ├── av_buffer.c │ ├── av_buffer.h │ ├── av_output.c │ ├── av_output.h │ ├── background.c │ ├── file_jpg.c │ ├── file_jpg.h │ ├── file_mjpg.c │ ├── file_mjpg.h │ ├── file_mp3.c │ ├── file_mp3.h │ ├── hr_timer.c │ ├── hr_timer.h │ ├── ir_decode.c │ ├── ir_decode.h │ ├── lv_conf.h │ ├── main.c │ ├── makefile │ ├── mmc_async_io.c │ ├── mmc_async_io.h │ ├── ui.c │ └── ui.h ├── arch │ └── riscv │ │ ├── assert.c │ │ ├── assert.h │ │ ├── boot.S │ │ ├── csr.h │ │ ├── exception.c │ │ ├── exception.h │ │ ├── exception_asm.h │ │ ├── init.c │ │ ├── linker_script.ld │ │ ├── timer.c │ │ └── timer.h ├── drivers │ ├── audio │ │ ├── audio.c │ │ └── audio.h │ ├── fb │ │ ├── fb_dev.c │ │ └── fb_dev.h │ ├── gpio │ │ └── gpio.h │ ├── irq │ │ ├── irq_ctrl.c │ │ └── irq_ctrl.h │ ├── jpeg │ │ ├── jpeg_hw.c │ │ └── jpeg_hw.h │ ├── sd │ │ ├── sd.h │ │ └── sd_card.c │ └── uart │ │ ├── uart_lite.c │ │ └── uart_lite.h ├── lib │ ├── _string.h │ ├── atoi.c │ ├── bcmp.c │ ├── isalpha.c │ ├── itoa.c │ ├── malloc.c │ ├── malloc.h │ ├── memchr.c │ ├── memcmp.c │ ├── memcpy.c │ ├── memmove.c │ ├── memset.c │ ├── printf.c │ ├── printf.h │ ├── rindex.c │ ├── stpcpy.c │ ├── strcat.c │ ├── strcmp.c │ ├── strcpy.c │ ├── strlen.c │ ├── strpbrk.c │ ├── strrchr.c │ ├── strtok.c │ ├── tolower.c │ └── toupper.c └── make │ ├── makefile.exe │ └── makefile.riscv ├── gateware ├── README.md ├── audio │ ├── audio.v │ ├── audio_defs.v │ ├── audio_fifo.v │ ├── audio_i2s.v │ ├── audio_spdif.v │ └── spdif_core.v ├── bootrom │ ├── bootrom.v │ └── bootrom_bridge.v ├── cdc │ ├── axi4_cdc.v │ └── axi_cdc_buffer.xci ├── cpu │ ├── dcache.v │ ├── dcache_axi.v │ ├── dcache_axi_axi.v │ ├── dcache_core.v │ ├── dcache_core_data_ram.v │ ├── dcache_core_tag_ram.v │ ├── dcache_if_pmem.v │ ├── dcache_mux.v │ ├── dcache_pmem_mux.v │ ├── icache.v │ ├── icache_data_ram.v │ ├── icache_tag_ram.v │ ├── riscv_alu.v │ ├── riscv_core.v │ ├── riscv_csr.v │ ├── riscv_csr_regfile.v │ ├── riscv_decode.v │ ├── riscv_decoder.v │ ├── riscv_defs.v │ ├── riscv_divider.v │ ├── riscv_exec.v │ ├── riscv_fetch.v │ ├── riscv_issue.v │ ├── riscv_lsu.v │ ├── riscv_mmu.v │ ├── riscv_multiplier.v │ ├── riscv_pipe_ctrl.v │ ├── riscv_regfile.v │ ├── riscv_top.v │ ├── riscv_trace_sim.v │ └── riscv_xilinx_2r1w.v ├── dbg_bridge │ ├── dbg_bridge.v │ ├── dbg_bridge_fifo.v │ └── dbg_bridge_uart.v ├── ddr │ ├── arty_ddr.v │ ├── mig_a.prj │ ├── mig_axis.xci │ └── mig_b.prj ├── dvi │ ├── dvi.v │ ├── dvi_framebuffer.v │ ├── dvi_framebuffer_defs.v │ ├── dvi_framebuffer_fifo.v │ ├── dvi_resync.v │ ├── dvi_serialiser.v │ └── dvi_tmds_encoder.v ├── jpeg_decoder │ ├── jpeg_decoder.v │ ├── jpeg_decoder_defs.v │ ├── jpeg_decoder_input_fifo.v │ └── jpeg_decoder_output_fifo.v ├── mmc │ ├── mmc_card.v │ ├── mmc_card_defs.v │ ├── mmc_card_fifo.v │ ├── mmc_cmd_deserialiser.v │ ├── mmc_cmd_serialiser.v │ ├── mmc_crc16.v │ ├── mmc_crc7.v │ ├── mmc_dat_deserialiser.v │ └── mmc_dat_serialiser.v ├── soc │ ├── core_soc.v │ ├── gpio.v │ ├── gpio_defs.v │ ├── irq_ctrl.v │ ├── irq_ctrl_defs.v │ ├── soc_arb.v │ ├── soc_axi_arb.v │ ├── soc_axi_dist.v │ ├── soc_axi_retime.v │ ├── uart_lite.v │ └── uart_lite_defs.v ├── top_hdmi │ ├── artix7_pll.v │ ├── arty_revb.xdc │ ├── axi4_dist.v │ ├── axi4_join.v │ ├── axi4_retime.v │ ├── axi4lite_dist.v │ ├── fpga_top.v │ ├── mclk_gen.v │ ├── reset_gen.v │ └── top.v ├── top_hdmi_720p │ ├── artix7_pll.v │ ├── arty_revb.xdc │ ├── axi4_dist.v │ ├── axi4_join.v │ ├── axi4_retime.v │ ├── axi4lite_dist.v │ ├── fpga_top.v │ ├── mclk_gen.v │ ├── reset_gen.v │ └── top.v ├── top_vga │ ├── artix7_pll.v │ ├── arty_revb.xdc │ ├── axi4_dist.v │ ├── axi4_join.v │ ├── axi4_retime.v │ ├── axi4lite_dist.v │ ├── fpga_top.v │ ├── mclk_gen.v │ ├── reset_gen.v │ └── top.v └── vga │ ├── vga_framebuffer.v │ ├── vga_framebuffer_defs.v │ └── vga_framebuffer_fifo.v └── scripts ├── README.md ├── convert.py └── legacy ├── README.md ├── convert_ffmpeg.py └── convert_mjpeg.py /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "firmware/rtos"] 2 | path = firmware/rtos 3 | url = https://github.com/ultraembedded/librtos.git 4 | [submodule "firmware/mp3"] 5 | path = firmware/mp3 6 | url = https://github.com/ultraembedded/libhelix-mp3.git 7 | [submodule "firmware/lvgl"] 8 | path = firmware/lvgl 9 | url = https://github.com/lvgl/lvgl.git 10 | [submodule "firmware/fs/fatfs"] 11 | path = firmware/fs/fatfs 12 | url = https://github.com/ultraembedded/fat_io_lib.git 13 | [submodule "gateware/jpeg_core"] 14 | path = gateware/jpeg_core 15 | url = https://github.com/ultraembedded/core_jpeg 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FPGA Media Player 2 | 3 | This project is a FPGA based media player which is capable of playing [Motion JPEG](https://en.wikipedia.org/wiki/Motion_JPEG) encoded video over HDMI or VGA on commonly available FPGA boards. 4 | 5 | ![](docs/demo.png) 6 | 7 | ## Features 8 | * 1280x720 [720p50 / 'standard HD'] 25fps video (also supports 24fps) 9 | * 44.1KHz stereo audio (I2S or SPDIF) 10 | * Hardware accelerated JPEG decoding 11 | * SD/MMC card interface (FAT16/32 support) 12 | * MP3 playback (SW codec) 13 | * JPEG stills display 14 | * IR remote control 15 | 16 | ## Rationale 17 | *Why?* For the fun of it! 18 | This project was an interesting test case for a number of my open-source digital IPs (RISC-V CPU, audio+video controllers), and also brings together various SW projects that I had written in years past (RTOS, FAT32 library). 19 | 20 | ## Supported Hardware 21 | * [Digilent Arty A7](https://reference.digilentinc.com/reference/programmable-logic/arty-a7/start) + [PMOD I2S2](https://reference.digilentinc.com/reference/pmod/pmodi2s2/start) + [PMOD MicroSD](https://reference.digilentinc.com/reference/pmod/pmodmicrosd/start) + [PMOD VGA](https://reference.digilentinc.com/reference/pmod/pmodvga/start) or PMOD2HDMI Breakout Cable + IR receiver 22 | 23 | ![ArtyA7](docs/arty.png) 24 | 25 | ## Cloning 26 | 27 | This repo contains submodules. 28 | Make sure to clone them all with the following command; 29 | 30 | ``` 31 | git clone --recursive https://github.com/ultraembedded/FPGAmp.git 32 | 33 | ``` 34 | 35 | ## Block Diagram 36 | ![Block Diagram](docs/block_diagram.png) 37 | 38 | ## Project Files 39 | 40 | The FPGA gateware for this project is constructed from various sub-projects; 41 | * [CPU - RISC-V](https://github.com/ultraembedded/riscv) 42 | * [Peripherals](https://github.com/ultraembedded/core_soc) 43 | * [UART -> AXI Debug Bridge](https://github.com/ultraembedded/core_dbg_bridge) 44 | * [SD/MMC interface](https://github.com/ultraembedded/core_mmc) 45 | * [JPEG decoder](https://github.com/ultraembedded/core_jpeg_decoder) 46 | * [Audio controller](https://github.com/ultraembedded/core_audio) 47 | * [DVI framebuffer](https://github.com/ultraembedded/core_dvi_framebuffer) 48 | 49 | On the firmware side, this project uses; 50 | * [Custom RTOS](https://github.com/ultraembedded/librtos) 51 | * [FAT32 Library](https://github.com/ultraembedded/fat_io_lib) 52 | * [MP3 decoder](https://github.com/ultraembedded/libhelix-mp3) 53 | * [LVGL User Interface](https://github.com/lvgl/lvgl) 54 | 55 | ## Getting Started 56 | 57 | The firmware needs to be built with the 32-bit RISC-V (RVIM) GCC; 58 | ``` 59 | # 1. Build firmware 60 | cd firmware/app 61 | make 62 | 63 | # 2. Copy firmware/app/build.riscv.boot/boot.bin to a FAT32 SD card 64 | ``` 65 | 66 | The bootROM in the FPGA fabric will automatically load 'boot.bin' from the SD card root directory. 67 | **NOTE**: The SD card must be formatted as FAT16 or FAT32 and not EXFAT! 68 | 69 | Debug messages will be comming out of the ArtyA7 USB-UART @ 1M baud (8N1). 70 | 71 | ## IR Remote 72 | The project can be controlled via an IR remote (NEC protocol, currently). 73 | The IR codes are device-specific but can be changed here; 74 | ``` 75 | // firmware/app/ir_decode.h 76 | #define IR_CMD_RIGHT 0x20df609f 77 | #define IR_CMD_LEFT 0x20dfe01f 78 | #define IR_CMD_DOWN 0x20df827d 79 | #define IR_CMD_UP 0x20df02fd 80 | #define IR_CMD_BACK 0x20df14eb 81 | ``` 82 | 83 | Handily, the UART outputs any received IR codes so it is relatively straight forward to tune the controls to a new remote. 84 | 85 | ![IR Connection](docs/ir_conn.png) 86 | -------------------------------------------------------------------------------- /bitstreams/README.md: -------------------------------------------------------------------------------- 1 | ## Bitstreams (and prebuilt FW) 2 | 3 | * Various prebuilt bitstreams (VGA or HDMI/DVI). 4 | * A prebuilt FW (boot.bin) that needs to be present on the SD/MMC root directory (FAT16/32 formatted). 5 | -------------------------------------------------------------------------------- /bitstreams/boot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/bitstreams/boot.bin -------------------------------------------------------------------------------- /bitstreams/fpga_hdmi.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/bitstreams/fpga_hdmi.bit -------------------------------------------------------------------------------- /bitstreams/fpga_hdmi_720p.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/bitstreams/fpga_hdmi_720p.bit -------------------------------------------------------------------------------- /bitstreams/fpga_vga.bit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/bitstreams/fpga_vga.bit -------------------------------------------------------------------------------- /docs/arty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/docs/arty.png -------------------------------------------------------------------------------- /docs/block_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/docs/block_diagram.png -------------------------------------------------------------------------------- /docs/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/docs/demo.png -------------------------------------------------------------------------------- /docs/ir_conn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/docs/ir_conn.png -------------------------------------------------------------------------------- /firmware/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/firmware/README.md -------------------------------------------------------------------------------- /firmware/app/av_buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "assert.h" 3 | #include "av_buffer.h" 4 | #include "csr.h" 5 | 6 | #ifndef CONFIG_AV_BUFFERS 7 | #define CONFIG_AV_BUFFERS 4 8 | #endif 9 | 10 | //----------------------------------------------------------------- 11 | // Locals 12 | //----------------------------------------------------------------- 13 | static struct av_buffer _buffers[CONFIG_AV_BUFFERS] __attribute__ ((aligned (512))); 14 | static struct link_list _buffer_list; 15 | 16 | //----------------------------------------------------------------- 17 | // avbuf_init 18 | //----------------------------------------------------------------- 19 | void avbuf_init(void) 20 | { 21 | int i; 22 | 23 | // Init buffer list 24 | list_init(&_buffer_list); 25 | 26 | // Add buffers to free list 27 | for (i=0;ilist_entry); 49 | 50 | csr_set_irq_enable(); 51 | 52 | // Reset details 53 | buf->length = 0; 54 | buf->audio_length = 0; 55 | 56 | return buf; 57 | } 58 | //----------------------------------------------------------------- 59 | // audiobuf_free 60 | //----------------------------------------------------------------- 61 | void avbuf_free(struct av_buffer *buf) 62 | { 63 | assert(buf); 64 | 65 | csr_clr_irq_enable(); 66 | list_insert_last(&_buffer_list, &buf->list_entry); 67 | csr_set_irq_enable(); 68 | } 69 | -------------------------------------------------------------------------------- /firmware/app/av_buffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __AV_BUFFER_H__ 2 | #define __AV_BUFFER_H__ 3 | 4 | #include 5 | #include "list.h" 6 | 7 | #define AV_BUF_DEPTH 2 8 | #define AV_BUF_FPS 24 9 | #define AV_BUF_SRATE 44100 10 | 11 | // Round up to 512 sector size 12 | #define AV_AUD_SIZE (((((AV_BUF_SRATE / AV_BUF_FPS) * 4) + 511) / 512) * 512) 13 | 14 | //----------------------------------------------------------------- 15 | // Types: 16 | //----------------------------------------------------------------- 17 | struct av_buffer 18 | { 19 | // Uncompressed output 20 | uint8_t frame_buffer[CONFIG_SCREEN_WIDTH * CONFIG_SCREEN_HEIGHT * AV_BUF_DEPTH] __attribute__ ((aligned (512))); 21 | 22 | // Source data buffer 23 | uint8_t src_data[(CONFIG_SCREEN_WIDTH * CONFIG_SCREEN_HEIGHT * AV_BUF_DEPTH) + AV_AUD_SIZE] __attribute__ ((aligned (512))); 24 | 25 | // Compressed data 26 | uint8_t *src_video; 27 | 28 | // PCM audio (stereo) 29 | uint32_t *src_audio; 30 | 31 | // JPEG image length 32 | int length; 33 | 34 | // Audio length 35 | int audio_length; 36 | 37 | struct link_node list_entry; 38 | }; 39 | 40 | //----------------------------------------------------------------- 41 | // Prototypes: 42 | //----------------------------------------------------------------- 43 | void avbuf_init(void); 44 | struct av_buffer* avbuf_alloc(void); 45 | void avbuf_free(struct av_buffer *buf); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /firmware/app/av_output.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "assert.h" 6 | #include "av_buffer.h" 7 | #include "jpeg_hw.h" 8 | #include "audio.h" 9 | #include "fb_dev.h" 10 | #include "kernel/thread.h" 11 | #include "kernel/mailbox.h" 12 | #include "av_output.h" 13 | 14 | //----------------------------------------------------------------- 15 | // Defines: 16 | //----------------------------------------------------------------- 17 | #define FRAME_BUFFER1 (0x3200000) 18 | #define FRAME_BUFFER2 (0x3400000) 19 | #define FRAME_BUFFER3 (0x3600000) 20 | 21 | //----------------------------------------------------------------- 22 | // uncached_ptr8: Convert to uncached alias 23 | //----------------------------------------------------------------- 24 | static uint8_t *uncached_ptr8(uint8_t *p) 25 | { 26 | return (uint8_t*)(((uint32_t)p) & 0x7FFFFFFF); 27 | } 28 | //----------------------------------------------------------------- 29 | // av_output: Video / Audio output thread 30 | //----------------------------------------------------------------- 31 | void* av_output(void * mbox) 32 | { 33 | printf("av_output: S\n"); 34 | jpeg_hw_reset(); 35 | 36 | // Init audio subsystem 37 | audio_init(CONFIG_AUDIO_BASE, -1, MCU_CLK, AUDIO_TARGET_I2S); 38 | 39 | int frame_idx = 0; 40 | uint32_t tl = 0; 41 | uint32_t tprev = 0; 42 | uint32_t fb[] = { FRAME_BUFFER1, FRAME_BUFFER2, FRAME_BUFFER3 }; 43 | int fb_idx = 0; 44 | 45 | while (1) 46 | { 47 | struct av_buffer* buf; 48 | mailbox_pend(mbox, &buf); 49 | 50 | // Video + Audio 51 | if (buf->length) 52 | { 53 | jpeg_hw_start((uint32_t)uncached_ptr8(buf->src_video), fb[fb_idx], buf->length); 54 | 55 | if (buf->audio_length) 56 | { 57 | while (audio_fifo_space() < buf->audio_length) 58 | thread_sleep(1); 59 | 60 | audio_load_samples(uncached_ptr8(buf->src_audio), buf->audio_length); 61 | } 62 | 63 | // 25fps minus some time... 64 | thread_sleep(35); 65 | 66 | while (jpeg_hw_busy()) 67 | ; 68 | 69 | //assert(!jpeg_hw_busy()); 70 | avbuf_free(buf); 71 | frame_idx++; 72 | 73 | fbdev_set_framebuffer(fb[fb_idx]); 74 | if (++fb_idx == 3) 75 | fb_idx = 0; 76 | } 77 | // Audio only 78 | else if (buf->audio_length) 79 | { 80 | while (audio_fifo_space() < buf->audio_length) 81 | thread_sleep(5); 82 | 83 | audio_load_samples(buf->src_audio, buf->audio_length); 84 | avbuf_free(buf); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /firmware/app/av_output.h: -------------------------------------------------------------------------------- 1 | #ifndef __AV_OUTPUT_H__ 2 | #define __AV_OUTPUT_H__ 3 | 4 | //----------------------------------------------------------------- 5 | // Prototypes: 6 | //----------------------------------------------------------------- 7 | void* av_output(void * mbox); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /firmware/app/file_jpg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "kernel/thread.h" 7 | #include "kernel/mailbox.h" 8 | 9 | #include "assert.h" 10 | #include "fat_filelib.h" 11 | #include "fat_string.h" 12 | 13 | #include "av_buffer.h" 14 | #include "file_jpg.h" 15 | 16 | //----------------------------------------------------------------------------- 17 | // uncached_ptr8: Convert to uncached alias 18 | //----------------------------------------------------------------------------- 19 | static uint8_t *uncached_ptr8(uint8_t *p) 20 | { 21 | return (uint8_t*)(((uint32_t)p) & 0x7FFFFFFF); 22 | } 23 | //----------------------------------------------------------------------------- 24 | // file_jpg_play: Load a JPEG 25 | //----------------------------------------------------------------------------- 26 | int file_jpg_play(const char *play_file, struct mailbox *mbox, int (*cb_stopped)(void)) 27 | { 28 | FL_FILE * f = fl_fopen((const char*)play_file, "rb"); 29 | if (!f) 30 | return 0; 31 | 32 | // Allocate a single buffer 33 | struct av_buffer* buf = NULL; 34 | while (!buf) 35 | { 36 | buf = avbuf_alloc(); 37 | if (!buf) 38 | thread_sleep(5); 39 | } 40 | 41 | // Load JPEG data 42 | buf->src_video = &buf->src_data[0]; 43 | buf->length = f->filelength; 44 | buf->audio_length = 0; 45 | fl_fread(uncached_ptr8((uint8_t*)buf->src_video), 1, buf->length, f); 46 | 47 | fl_fclose(f); 48 | f = NULL; 49 | 50 | // Send to display 51 | mailbox_post(mbox, (uint32_t)buf); 52 | 53 | // Wait for user input to stop 54 | while (1) 55 | { 56 | thread_sleep(10); 57 | if (cb_stopped()) 58 | break; 59 | } 60 | 61 | return 1; 62 | } 63 | -------------------------------------------------------------------------------- /firmware/app/file_jpg.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILE_JPG_H__ 2 | #define __FILE_JPG_H__ 3 | 4 | #include "kernel/mailbox.h" 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | int file_jpg_play(const char *filename, struct mailbox *mbox, int (*cb_stopped)(void)); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /firmware/app/file_mjpg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "kernel/thread.h" 7 | #include "kernel/mailbox.h" 8 | 9 | #include "assert.h" 10 | #include "fat_filelib.h" 11 | #include "fat_string.h" 12 | 13 | #include "av_buffer.h" 14 | #include "mmc_async_io.h" 15 | #include "file_mjpg.h" 16 | 17 | //----------------------------------------------------------------- 18 | // Locals: 19 | //----------------------------------------------------------------- 20 | /* 21 | File Format: 22 | 23 | |-------------------------| 24 | | BHeader (512 bytes) | 25 | |-------------------------| 26 | | Video Frame + Pad | 27 | |-------------------------| x 128 28 | | Audio Frame + Pad | 29 | |-------------------------| 30 | | BHeader (512 bytes) | 31 | |-------------------------| 32 | | Video Frame + Pad | 33 | |-------------------------| x 128 34 | | Audio Frame + Pad | 35 | */ 36 | 37 | struct headerb 38 | { 39 | uint32_t frame_size[128]; 40 | }; 41 | 42 | struct audiob 43 | { 44 | uint32_t samples[1764]; 45 | uint8_t padding[112]; 46 | }; 47 | 48 | static struct headerb hdr_b __attribute__ ((aligned (512))); 49 | 50 | //----------------------------------------------------------------------------- 51 | // fl_get_start_sector: Get first sector used by file (test only) 52 | //----------------------------------------------------------------------------- 53 | static uint32 fl_get_start_sector(void* file) 54 | { 55 | return fatfs_lba_of_cluster(fl_get_fs(), ((FL_FILE*)file)->startcluster); 56 | } 57 | //----------------------------------------------------------------- 58 | // uncached_ptr8: Convert to uncached alias 59 | //----------------------------------------------------------------- 60 | static uint8_t *uncached_ptr8(uint8_t *p) 61 | { 62 | return (uint8_t*)(((uint32_t)p) & 0x7FFFFFFF); 63 | } 64 | //----------------------------------------------------------------------------- 65 | // file_mjpg_play: Play motion JPEG file 66 | //----------------------------------------------------------------------------- 67 | int file_mjpg_play(const char *play_file, struct mailbox *mbox, int fps, int (*cb_stopped)(void)) 68 | { 69 | FL_FILE * f = fl_fopen((const char*)play_file, "rb"); 70 | if (!f) 71 | return 0; 72 | 73 | uint32_t total_sectors = (f->filelength + 511) / 512; 74 | // TODO: Currently assuming linear file storage for read speed - FIXME 75 | uint32_t current_sector = fl_get_start_sector(f); 76 | uint32_t last_sector = current_sector + total_sectors; 77 | 78 | int audio_samples = (AV_BUF_SRATE / fps); 79 | int frame_idx = 0; 80 | int subframe = 0; 81 | uint32_t *hdr_frame_sz = (uint32_t *)uncached_ptr8((uint8_t*)&hdr_b.frame_size[0]); 82 | while (1) 83 | { 84 | struct av_buffer* buf = avbuf_alloc(); 85 | if (buf) 86 | { 87 | // Read 128 frame block header 88 | if (subframe == 0) 89 | mmc_async_io_read(current_sector++, (uint8_t*)&hdr_b, 1); 90 | 91 | int audio_padded; 92 | if (fps != 25 && (subframe & 1)) 93 | audio_padded = (((((audio_samples+1) * 4) + 511) / 512) * 512); 94 | else 95 | audio_padded = ((((audio_samples * 4) + 511) / 512) * 512); 96 | 97 | uint32_t size = hdr_frame_sz[subframe]; 98 | uint32_t size_pad= ((size + 511) / 512) * 512; 99 | uint32_t sectors = ((size + 511) / 512) + (audio_padded / 512); 100 | 101 | // Invalid video frame length, end of video detected. 102 | if (size == 0) 103 | { 104 | avbuf_free(buf); 105 | break; 106 | } 107 | 108 | mmc_async_io_read(current_sector, uncached_ptr8(buf->src_data), sectors); 109 | current_sector += sectors; 110 | 111 | // Find pointers to content 112 | buf->src_video = &buf->src_data[0]; 113 | buf->src_audio = (uint32_t*)&buf->src_data[size_pad]; 114 | buf->length = size; 115 | 116 | if (fps != 25 && (subframe & 1)) 117 | buf->audio_length = (AV_BUF_SRATE / fps) + 1; 118 | else 119 | buf->audio_length = (AV_BUF_SRATE / fps); 120 | 121 | if (++subframe == 128) 122 | subframe = 0; 123 | 124 | mailbox_post(mbox, (uint32_t)buf); 125 | frame_idx++; 126 | 127 | if (current_sector >= last_sector) 128 | break; 129 | } 130 | else 131 | thread_sleep(10); 132 | 133 | if (cb_stopped()) 134 | { 135 | printf("User stopped playback...\n"); 136 | break; 137 | } 138 | } 139 | fl_fclose(f); 140 | return 1; 141 | } 142 | -------------------------------------------------------------------------------- /firmware/app/file_mjpg.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILE_MJPG_H__ 2 | #define __FILE_MJPG_H__ 3 | 4 | #include "kernel/mailbox.h" 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | int file_mjpg_play(const char *play_file, struct mailbox *mbox, int fps, int (*cb_stopped)(void)); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /firmware/app/file_mp3.h: -------------------------------------------------------------------------------- 1 | #ifndef __FILE_MP3_H__ 2 | #define __FILE_MP3_H__ 3 | 4 | #include "kernel/mailbox.h" 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | int file_mp3_play(const char *filename, struct mailbox *mbox, int (*cb_stopped)(void)); 10 | 11 | #endif // __FILE_MP3_H__ 12 | -------------------------------------------------------------------------------- /firmware/app/hr_timer.c: -------------------------------------------------------------------------------- 1 | #include "hr_timer.h" 2 | 3 | static uint32_t _ticks_per_ms = MCU_CLK / 1000; 4 | static uint32_t _ticks_per_us = MCU_CLK / 1000000; 5 | 6 | //-------------------------------------------------------------------------- 7 | // hrtimer_diffms: 8 | //-------------------------------------------------------------------------- 9 | int32_t hrtimer_diffms(t_tick a, t_tick b) 10 | { 11 | return hrtimer_diff(a, b) / _ticks_per_ms; 12 | } 13 | //-------------------------------------------------------------------------- 14 | // hrtimer_diffus: 15 | //-------------------------------------------------------------------------- 16 | int32_t hrtimer_diffus(t_tick a, t_tick b) 17 | { 18 | return hrtimer_diff(a, b) / _ticks_per_us; 19 | } 20 | //-------------------------------------------------------------------------- 21 | // hrtimer_delayms: 22 | //-------------------------------------------------------------------------- 23 | void hrtimer_delayms(int time_ms) 24 | { 25 | t_tick t = hrtimer_now() + (_ticks_per_ms * time_ms); 26 | 27 | while (hrtimer_now() < t) 28 | ; 29 | } 30 | //-------------------------------------------------------------------------- 31 | // hrtimer_delayus: 32 | //-------------------------------------------------------------------------- 33 | void hrtimer_delayus(int time_us) 34 | { 35 | t_tick t = hrtimer_now() + (_ticks_per_us * time_us); 36 | 37 | while (hrtimer_now() < t) 38 | ; 39 | } 40 | //-------------------------------------------------------------------------- 41 | // hrtimer_ms_to_ticks: 42 | //-------------------------------------------------------------------------- 43 | t_tick hrtimer_ms_to_ticks(uint32_t time_ms) 44 | { 45 | return (_ticks_per_ms * time_ms); 46 | } 47 | //-------------------------------------------------------------------------- 48 | // hrtimer_us_to_ticks: 49 | //-------------------------------------------------------------------------- 50 | t_tick hrtimer_us_to_ticks(uint32_t time_us) 51 | { 52 | return (_ticks_per_us * time_us); 53 | } 54 | //-------------------------------------------------------------------------- 55 | // hrtimer_ticks_to_us: 56 | //-------------------------------------------------------------------------- 57 | int32_t hrtimer_ticks_to_us(t_tick ticks) 58 | { 59 | return (ticks / _ticks_per_us); 60 | } 61 | //-------------------------------------------------------------------------- 62 | // hrtimer_ticks_to_ms: 63 | //-------------------------------------------------------------------------- 64 | int32_t hrtimer_ticks_to_ms(t_tick ticks) 65 | { 66 | return (ticks / _ticks_per_ms); 67 | } 68 | -------------------------------------------------------------------------------- /firmware/app/hr_timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __HR_TIMER_H__ 2 | #define __HR_TIMER_H__ 3 | 4 | #include 5 | #include "timer.h" 6 | 7 | //----------------------------------------------------------------- 8 | // Defines: 9 | //----------------------------------------------------------------- 10 | typedef int32_t t_tick; 11 | 12 | //----------------------------------------------------------------- 13 | // Prototypes: 14 | //----------------------------------------------------------------- 15 | static t_tick hrtimer_now(void) { return timer_get_mtime(); } 16 | static int32_t hrtimer_diff(t_tick a, t_tick b) { return (int32_t)(a - b); } 17 | int32_t hrtimer_diffms(t_tick a, t_tick b); 18 | int32_t hrtimer_diffus(t_tick a, t_tick b); 19 | void hrtimer_delayms(int time_ms); 20 | void hrtimer_delayus(int time_us); 21 | t_tick hrtimer_ms_to_ticks(uint32_t time_ms); 22 | t_tick hrtimer_us_to_ticks(uint32_t time_us); 23 | int32_t hrtimer_ticks_to_us(t_tick ticks); 24 | int32_t hrtimer_ticks_to_ms(t_tick ticks); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /firmware/app/ir_decode.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gpio.h" 3 | #include "hr_timer.h" 4 | #include "irq_ctrl.h" 5 | #include "ir_decode.h" 6 | #include "assert.h" 7 | 8 | #include "kernel/critical.h" 9 | #include "kernel/os_assert.h" 10 | #include "kernel/list.h" 11 | #include "kernel/thread.h" 12 | #include "kernel/mutex.h" 13 | #include "kernel/semaphore.h" 14 | #include "kernel/event.h" 15 | #include "kernel/mutex.h" 16 | #include "kernel/mailbox.h" 17 | 18 | #define GPIO_EDGE_FALLING(pin) gpio_configure_int(pin, 1, 1, 0) 19 | #define GPIO_EDGE_RISING(pin) gpio_configure_int(pin, 1, 1, 1) 20 | 21 | //----------------------------------------------------------------- 22 | // Locals: 23 | //----------------------------------------------------------------- 24 | static struct semaphore m_sema; 25 | static int m_irq_num; 26 | static int m_pin; 27 | 28 | MAILBOX_DECL(ir_cmd, 4); 29 | 30 | static uint32_t m_last_time = 0; 31 | static int m_last_pin = 1; 32 | static int m_bit_count = 0; 33 | static uint32_t m_ir_code; 34 | static int m_last_delta = 0; 35 | static uint32_t m_last_cmd_time = 0; 36 | static uint32_t m_last_ir_code = 0; 37 | 38 | //----------------------------------------------------------------- 39 | // ir_irq_handler: IR pin transition 40 | //----------------------------------------------------------------- 41 | static void* ir_irq_handler(void *ctx, int irq_number) 42 | { 43 | int pin_val = gpio_input_bit(m_pin); 44 | uint32_t now = hrtimer_now(); 45 | int delta_us = hrtimer_diffus(now, m_last_time); 46 | m_last_time = now; 47 | 48 | if (m_last_pin) 49 | { 50 | assert(pin_val == 0); 51 | 52 | // Leader code 53 | if (delta_us >= 4000) 54 | { 55 | m_bit_count = 0; 56 | m_ir_code = 0; 57 | } 58 | else 59 | m_bit_count++; 60 | 61 | // Shift data PCM data in 62 | int v = (delta_us <= 1000) ? 0 : 1; 63 | m_ir_code <<= 1; 64 | m_ir_code |= v; 65 | 66 | // Full IR code received 67 | if (m_bit_count == 32) 68 | { 69 | m_last_cmd_time = now; 70 | m_last_ir_code = m_ir_code; 71 | semaphore_post_irq(&m_sema); 72 | } 73 | // Detect repeat code 74 | else if (m_bit_count == 1 && m_last_delta >= 9000 && delta_us >= 2000 && hrtimer_diffus(now, m_last_cmd_time) > 100000) 75 | { 76 | m_ir_code = m_last_ir_code; 77 | m_last_cmd_time = now; 78 | semaphore_post_irq(&m_sema); 79 | } 80 | 81 | // Detect rising edge 82 | GPIO_EDGE_RISING(m_pin); 83 | gpio_interrupt_ack(1 << m_pin); 84 | irqctrl_acknowledge(m_irq_num); 85 | } 86 | else 87 | { 88 | assert(pin_val == 1); 89 | 90 | // Detect falling edge 91 | GPIO_EDGE_FALLING(m_pin); 92 | gpio_interrupt_ack(1 << m_pin); 93 | irqctrl_acknowledge(m_irq_num); 94 | irqctrl_enable_irq(m_irq_num, 1); 95 | } 96 | m_last_pin = pin_val; 97 | m_last_delta = delta_us; 98 | 99 | return ctx; 100 | } 101 | //----------------------------------------------------------------- 102 | // ir_decode_init: 103 | //----------------------------------------------------------------- 104 | void ir_decode_init(int pin, int irq_number) 105 | { 106 | m_pin = pin; 107 | m_irq_num = irq_number; 108 | 109 | gpio_enable_outputs(0); 110 | GPIO_EDGE_FALLING(m_pin); 111 | gpio_interrupt_ack(1 << m_pin); 112 | 113 | // Hookup GPIO interrupt handler 114 | irqctrl_set_handler(m_irq_num, ir_irq_handler); 115 | 116 | // Reset and enable 117 | irqctrl_acknowledge(m_irq_num); 118 | irqctrl_enable_irq(m_irq_num, 1); 119 | } 120 | //----------------------------------------------------------------- 121 | // ir_decode_thread: 122 | //----------------------------------------------------------------- 123 | void *ir_decode_thread(void *arg) 124 | { 125 | while (1) 126 | { 127 | // Wait for IRQ 128 | if (semaphore_timed_pend(&m_sema, 100)) 129 | mailbox_post(&mbox_ir_cmd, (void*)(uint32_t)m_ir_code); 130 | // Polled UART control 131 | else 132 | { 133 | int ch = console_getchar(); 134 | if (ch == 'a') 135 | mailbox_post(&mbox_ir_cmd, (void*)IR_CMD_UP); 136 | else if (ch == 'z') 137 | mailbox_post(&mbox_ir_cmd, (void*)IR_CMD_DOWN); 138 | else if (ch == 'x') 139 | mailbox_post(&mbox_ir_cmd, (void*)IR_CMD_LEFT); 140 | else if (ch == 'c') 141 | mailbox_post(&mbox_ir_cmd, (void*)IR_CMD_RIGHT); 142 | else if (ch == 'v') 143 | mailbox_post(&mbox_ir_cmd, (void*)IR_CMD_BACK); 144 | } 145 | } 146 | } 147 | //----------------------------------------------------------------- 148 | // ir_ready: 149 | //----------------------------------------------------------------- 150 | int ir_ready(void) 151 | { 152 | return mbox_ir_cmd.count != 0; 153 | } 154 | //----------------------------------------------------------------- 155 | // ir_pop: 156 | //----------------------------------------------------------------- 157 | uint32_t ir_pop(void) 158 | { 159 | uint32_t value = 0; 160 | mailbox_pend(&mbox_ir_cmd, (void*)&value); 161 | return value; 162 | } -------------------------------------------------------------------------------- /firmware/app/ir_decode.h: -------------------------------------------------------------------------------- 1 | #ifndef __IR_DECODE_H__ 2 | #define __IR_DECODE_H__ 3 | 4 | //----------------------------------------------------------------- 5 | // Defines: 6 | //----------------------------------------------------------------- 7 | // Specific to particular remote control 8 | #define IR_CMD_RIGHT 0x20df609f 9 | #define IR_CMD_LEFT 0x20dfe01f 10 | #define IR_CMD_DOWN 0x20df827d 11 | #define IR_CMD_UP 0x20df02fd 12 | #define IR_CMD_BACK 0x20df14eb 13 | 14 | //----------------------------------------------------------------- 15 | // Prototypes: 16 | //----------------------------------------------------------------- 17 | void ir_decode_init(int pin, int irq_number); 18 | void * ir_decode_thread(void *arg); 19 | int ir_ready(void); 20 | uint32_t ir_pop(void); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /firmware/app/makefile: -------------------------------------------------------------------------------- 1 | SRC_DIR = ./ 2 | EXTRA_CFLAGS = -I ../ 3 | 4 | # Drivers 5 | EXTRA_CFLAGS += -DCONFIG_IRQCTRL_BASE=0x90000000 6 | EXTRA_CFLAGS += -DSD_CTRL_BASE=0x96000000 7 | EXTRA_CFLAGS += -DINCLUDE_SD_CARD_DRIVER 8 | EXTRA_CFLAGS += -DCONFIG_SD_MULTI_READ 9 | EXTRA_CFLAGS += -DCONFIG_JPEG_HW 10 | EXTRA_CFLAGS += -DCONFIG_IRQCTRL 11 | EXTRA_CFLAGS += -DCONFIG_FRAMEBUFFER 12 | EXTRA_CFLAGS += -DCONFIG_UARTLITE 13 | EXTRA_CFLAGS += -DCONFIG_UARTLITE_BASE=0x92000000 14 | EXTRA_CFLAGS += -DCONFIG_UARTLITE_CONSOLE 15 | EXTRA_CFLAGS += -DCONFIG_NO_RPC_SUPPORT 16 | EXTRA_CFLAGS += -DCPU_KHZ=60000 17 | 18 | EXTRA_CFLAGS += -DCONFIG_FB_DEV_BASE=0x95000000 19 | EXTRA_CFLAGS += -DCONFIG_AUDIO_BASE=0x93000000 20 | 21 | EXTRA_CFLAGS += -DCONFIG_SCREEN_WIDTH=1280 22 | EXTRA_CFLAGS += -DCONFIG_SCREEN_HEIGHT=720 23 | 24 | # RTOS 25 | SRC_DIR += ../rtos 26 | SRC_DIR += ../rtos/arch/riscv 27 | SRC_DIR += ../rtos/kernel 28 | EXTRA_CFLAGS += -DINCLUDE_MUTEX 29 | EXTRA_CFLAGS += -DINCLUDE_SEMAPHORE 30 | EXTRA_CFLAGS += -DINCLUDE_MAILBOX 31 | EXTRA_CFLAGS += -DINCLUDE_EVENTS 32 | EXTRA_CFLAGS += -DPLATFORM_IDLE_TASK_STACK=1024 33 | EXTRA_CFLAGS += -DINCLUDE_RTOS 34 | EXTRA_CFLAGS += -DMCU_CLK=60000000 35 | 36 | # FATFS 37 | SRC_DIR += ../fs/fatfs/src 38 | EXTRA_CFLAGS+= -DFATFS_INC_TEST_HOOKS 39 | 40 | # MP3 Codec 41 | EXTRA_CFLAGS+= -DINCLUDE_MP3_SUPPORT 42 | SRC_DIR += ../mp3/real 43 | SRC_DIR += ../mp3/pub 44 | SRC_DIR += ../mp3 45 | 46 | # LIB: printf, etc 47 | SRC_DIR += ../lib 48 | EXTRA_CFLAGS+= -DCONFIG_MALLOC 49 | EXTRA_CFLAGS+= -DCONFIG_MALLOC_SIZE=131072 50 | 51 | # LVGL Library 52 | EXTRA_CFLAGS+= -DLV_CONF_INCLUDE_SIMPLE 53 | LVGL_DIR_NAME ?= lvgl 54 | LVGL_DIR ?= ../ 55 | EXTRA_CFLAGS+= -I$(LVGL_DIR)/ 56 | include $(LVGL_DIR)/lvgl/lvgl.mk 57 | EXTRA_SRC:= $(sort $(ASRCS) $(CSRCS) $(MAINSRC)) 58 | 59 | MEM_SIZE=0x3000000 60 | OPT = 2 61 | 62 | TARGET=boot 63 | ARCH=riscv 64 | 65 | MAKE_DIR=../make 66 | include $(MAKE_DIR)/makefile.exe -------------------------------------------------------------------------------- /firmware/app/mmc_async_io.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "assert.h" 4 | #include "csr.h" 5 | #include "sd.h" 6 | 7 | #include "kernel/critical.h" 8 | #include "kernel/os_assert.h" 9 | #include "kernel/list.h" 10 | #include "kernel/thread.h" 11 | #include "kernel/mutex.h" 12 | #include "kernel/semaphore.h" 13 | #include "kernel/event.h" 14 | #include "kernel/mutex.h" 15 | #include "kernel/mailbox.h" 16 | 17 | #include "irq_ctrl.h" 18 | 19 | //----------------------------------------------------------------- 20 | // Locals 21 | //----------------------------------------------------------------- 22 | static struct semaphore m_mmc_sema; 23 | static int m_irq_num; 24 | static int m_max_sectors; 25 | 26 | //----------------------------------------------------------------- 27 | // mmc_irq_handler: Low level IRQ handler (operation complete) 28 | //----------------------------------------------------------------- 29 | static void* mmc_irq_handler(void *ctx, int irq) 30 | { 31 | semaphore_post_irq(&m_mmc_sema); 32 | 33 | // Reset and disable 34 | irqctrl_acknowledge(m_irq_num); 35 | irqctrl_enable_irq(m_irq_num, 0); 36 | return ctx; 37 | } 38 | //----------------------------------------------------------------- 39 | // mmc_async_io_init: Initialisation 40 | //----------------------------------------------------------------- 41 | void mmc_async_io_init(int irq_num, int max_sectors) 42 | { 43 | semaphore_init(&m_mmc_sema, 0); 44 | m_irq_num = irq_num; 45 | m_max_sectors = max_sectors; 46 | 47 | // Hookup SD/MMC interrupt handler 48 | irqctrl_set_handler(m_irq_num, mmc_irq_handler); 49 | 50 | // Reset and disable 51 | irqctrl_acknowledge(m_irq_num); 52 | irqctrl_enable_irq(m_irq_num, 0); 53 | } 54 | //----------------------------------------------------------------- 55 | // mmc_async_io_read: MMC read using DMA with thread yield 56 | //----------------------------------------------------------------- 57 | int mmc_async_io_read(uint32_t start_block, uint8_t *buffer, uint32_t sector_count) 58 | { 59 | uint32_t remain = sector_count; 60 | 61 | while (remain) 62 | { 63 | uint32_t count = remain; 64 | if (count >= m_max_sectors) 65 | count = m_max_sectors; 66 | 67 | // Reset and enable IRQ 68 | irqctrl_acknowledge(m_irq_num); 69 | irqctrl_enable_irq(m_irq_num, 1); 70 | 71 | // Start async transfer 72 | sd_readsector_dma_start(start_block, buffer, count); 73 | buffer += (512 * count); 74 | start_block += count; 75 | remain -= count; 76 | 77 | // Wait for completion 78 | if (!semaphore_timed_pend(&m_mmc_sema, 1000)) 79 | { 80 | assert(!"ERROR: SD card timeout"); 81 | } 82 | 83 | // Close async transfer after completion 84 | sd_readsector_dma_end(); 85 | } 86 | 87 | return 1; 88 | } 89 | -------------------------------------------------------------------------------- /firmware/app/mmc_async_io.h: -------------------------------------------------------------------------------- 1 | #ifndef __MMC_ASYNC_IO_H__ 2 | #define __MMC_ASYNC_IO_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | void mmc_async_io_init(int irq_num, int max_sectors); 10 | int mmc_async_io_read(uint32_t start_block, uint8_t *buffer, uint32_t sector_count); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /firmware/app/ui.h: -------------------------------------------------------------------------------- 1 | #ifndef __UI_H__ 2 | #define __UI_H__ 3 | 4 | #include "lvgl/lvgl.h" 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | void ui_init(void); 10 | void ui_add_entry(char *name, void (*handler)(lv_obj_t * obj, lv_event_t event), const void * img); 11 | void *ui_thread(void *arg); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /firmware/arch/riscv/assert.c: -------------------------------------------------------------------------------- 1 | #include 2 | extern void _exit(int rc); 3 | 4 | //----------------------------------------------------------------- 5 | // assert_handler: 6 | //----------------------------------------------------------------- 7 | void assert_handler(const char * type, const char *reason, const char *file, int line) 8 | { 9 | printf("%s: %s (%s:%d)\n", type, reason, file, line); 10 | _exit(-1); 11 | } 12 | -------------------------------------------------------------------------------- /firmware/arch/riscv/assert.h: -------------------------------------------------------------------------------- 1 | #ifndef __ASSERT_H__ 2 | #define __ASSERT_H__ 3 | 4 | extern void assert_handler(const char * type, const char *reason, const char *file, int line); 5 | 6 | #define assert(exp) do { if (!(exp)) assert_handler("ASSERT", #exp, __FILE__, __LINE__ ); } while (0) 7 | #define panic(reason) do { assert_handler("PANIC", #reason, __FILE__, __LINE__ ); } while (0) 8 | 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /firmware/arch/riscv/boot.S: -------------------------------------------------------------------------------- 1 | 2 | .global init 3 | .global main 4 | .global main_machine 5 | .global irq_handler 6 | 7 | ##################################################### 8 | # Entry point 9 | ##################################################### 10 | .org 0x0 11 | .section .boot 12 | boot_vector: 13 | j start 14 | 15 | ##################################################### 16 | # IPC Vector 17 | ##################################################### 18 | .org 0x8 19 | ipc_vector: 20 | .zero 21 | 22 | ##################################################### 23 | # ISR Vector 24 | ##################################################### 25 | .org 0x10 26 | j int_vector 27 | 28 | ##################################################### 29 | # IPC Vector 30 | ##################################################### 31 | # Request ID 32 | .org 0x14 33 | ipc_request: 34 | .space 4, 0 35 | 36 | # Request frame pointer 37 | .org 0x18 38 | ipc_frame: 39 | .space 4, 0 40 | 41 | .section .text 42 | 43 | ##################################################### 44 | # Arg handling 45 | ##################################################### 46 | .org 0x20 47 | arg_argc: 48 | .space 4, 0 49 | arg_argv: 50 | .space 256, 0 51 | 52 | ##################################################### 53 | # Actual ISR vector 54 | ##################################################### 55 | int_vector: 56 | #include "exception_asm.h" 57 | 58 | ##################################################### 59 | # Start 60 | ##################################################### 61 | start: 62 | 63 | # Setup stack pointer 64 | lui sp, %hi(_sp) 65 | add sp, sp, %lo(_sp) 66 | 67 | 68 | # Setup IRQ vector 69 | lui t0, %hi(isr_vector) 70 | add t0, t0, %lo(isr_vector) 71 | csrw mtvec, t0 72 | 73 | # t0 = _bss_start 74 | lui t0,%hi(_bss_start) 75 | add t0,t0,%lo(_bss_start) 76 | 77 | # t1 = _end 78 | lui t1,%hi(_end) 79 | add t1,t1,%lo(_end) 80 | 81 | bss_clear: 82 | #ifndef SKIP_BSS_INIT 83 | sw x0, (0)(t0) # Write 0x00 to mem[t0] 84 | add t0, t0, 4 # t0 += 4 85 | blt t0, t1, bss_clear # Branch back to bss_clear if (t0 < t1) 86 | #endif 87 | 88 | # Jump to init 89 | jal init 90 | 91 | # Run main 92 | # a0 = argc 93 | la a0, arg_argc 94 | lw a0, 0(a0) 95 | # a1 = argv 96 | la a1, arg_argv 97 | jal main 98 | 99 | # Exit 100 | jal _exit 101 | 102 | ##################################################### 103 | # Exit 104 | ##################################################### 105 | .global _exit 106 | _exit: 107 | andi a0, a0, 0xFF 108 | csrw dscratch, a0 109 | _exit_loop: 110 | jal _exit_loop 111 | 112 | -------------------------------------------------------------------------------- /firmware/arch/riscv/exception.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXCEPTION_H__ 2 | #define __EXCEPTION_H__ 3 | 4 | #include 5 | #include "csr.h" 6 | 7 | //----------------------------------------------------------------- 8 | // Defines: 9 | //----------------------------------------------------------------- 10 | #define REG_RA 1 11 | #define REG_SP 2 12 | #define REG_ARG0 10 13 | #define REG_RET REG_ARG0 14 | #define NUM_GP_REG 32 15 | #define NUM_CSR_REG 3 16 | 17 | #define CAUSE_MISALIGNED_FETCH 0 18 | #define CAUSE_FAULT_FETCH 1 19 | #define CAUSE_ILLEGAL_INSTRUCTION 2 20 | #define CAUSE_BREAKPOINT 3 21 | #define CAUSE_MISALIGNED_LOAD 4 22 | #define CAUSE_FAULT_LOAD 5 23 | #define CAUSE_MISALIGNED_STORE 6 24 | #define CAUSE_FAULT_STORE 7 25 | #define CAUSE_ECALL_U 8 26 | #define CAUSE_ECALL_S 9 27 | #define CAUSE_ECALL_M 11 28 | #define CAUSE_PAGE_FAULT_INST 12 29 | #define CAUSE_PAGE_FAULT_LOAD 13 30 | #define CAUSE_PAGE_FAULT_STORE 15 31 | #define CAUSE_INTERRUPT (1 << 31) 32 | 33 | //----------------------------------------------------------------- 34 | // Types: 35 | //----------------------------------------------------------------- 36 | struct irq_context 37 | { 38 | uint32_t pc; 39 | uint32_t status; 40 | uint32_t cause; 41 | uint32_t reg[NUM_GP_REG]; 42 | }; 43 | 44 | typedef struct irq_context *(*fp_exception)(struct irq_context *ctx); 45 | typedef struct irq_context *(*fp_irq)(struct irq_context *ctx); 46 | typedef struct irq_context *(*fp_syscall)(struct irq_context *ctx); 47 | 48 | //----------------------------------------------------------------- 49 | // context_irq_enable: Set future interrupt enable 50 | //----------------------------------------------------------------- 51 | static void context_irq_enable(struct irq_context *ctx, int enable) 52 | { 53 | // MPIE becomes MIE on return from exception 54 | ctx->status &= ~SR_MPIE; 55 | ctx->status |= (enable ? SR_MPIE : 0); 56 | } 57 | 58 | //----------------------------------------------------------------- 59 | // Prototypes: 60 | //----------------------------------------------------------------- 61 | struct irq_context * exception_handler(struct irq_context *ctx); 62 | void exception_set_irq_handler(fp_irq irq_handler); 63 | fp_irq exception_get_irq_handler(void); 64 | void exception_set_timer_handler(fp_irq irq_handler); 65 | void exception_set_syscall_handler(fp_syscall syscall_handler); 66 | void exception_set_handler(int cause, fp_exception handler); 67 | void exception_dump_ctx(struct irq_context *ctx); 68 | struct irq_context * exception_makecontext(uint32_t *stack, uint32_t stack_size, void (*func)(), void *arg); 69 | void exception_return(struct irq_context *ucp); 70 | void exception_syscall(uint32_t arg, ...); 71 | 72 | #endif 73 | 74 | -------------------------------------------------------------------------------- /firmware/arch/riscv/exception_asm.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // ISR Vector 3 | //----------------------------------------------------------------- 4 | .global isr_vector 5 | .global exception_return 6 | isr_vector: 7 | #ifdef EXCEPTION_SP_FROM_MSCRATCH 8 | csrrw sp, mscratch, sp 9 | #endif 10 | addi sp, sp, -(35*4) 11 | 12 | // Save registers 13 | sw x31, (4*34)(sp) 14 | sw x30, (4*33)(sp) 15 | sw x29, (4*32)(sp) 16 | sw x28, (4*31)(sp) 17 | sw x27, (4*30)(sp) 18 | sw x26, (4*29)(sp) 19 | sw x25, (4*28)(sp) 20 | sw x24, (4*27)(sp) 21 | sw x23, (4*26)(sp) 22 | sw x22, (4*25)(sp) 23 | sw x21, (4*24)(sp) 24 | sw x20, (4*23)(sp) 25 | sw x19, (4*22)(sp) 26 | sw x18, (4*21)(sp) 27 | sw x17, (4*20)(sp) 28 | sw x16, (4*19)(sp) 29 | sw x15, (4*18)(sp) 30 | sw x14, (4*17)(sp) 31 | sw x13, (4*16)(sp) 32 | sw x12, (4*15)(sp) 33 | sw x11, (4*14)(sp) 34 | sw x10, (4*13)(sp) 35 | sw x9, (4*12)(sp) 36 | sw x8, (4*11)(sp) 37 | sw x7, (4*10)(sp) 38 | sw x6, (4* 9)(sp) 39 | sw x5, (4* 8)(sp) 40 | sw x4, (4* 7)(sp) 41 | sw x3, (4* 6)(sp) 42 | sw x2, (4* 5)(sp) // SP 43 | sw x1, (4* 4)(sp) // RA 44 | //sw x0, (4* 3)(sp) // ZERO 45 | 46 | csrr s0, mcause 47 | sw s0, (4* 2)(sp) 48 | 49 | csrr s0, mstatus 50 | sw s0, (4* 1)(sp) 51 | 52 | csrr s0, mepc 53 | sw s0, (4* 0)(sp) 54 | 55 | // Call ISR handler 56 | mv a0, sp 57 | jal exception_handler 58 | 59 | exception_return: 60 | mv sp, a0 61 | 62 | // Restore registers 63 | lw s0, (4* 0)(sp) 64 | csrw mepc, s0 65 | 66 | lw s0, (4* 1)(sp) 67 | csrw mstatus, s0 68 | 69 | //lw s0, (4* 2)(sp) 70 | //csrw mcause, s0 71 | 72 | // lw(HOLE): x0 / ZERO 73 | lw x1, (4* 4)(sp) 74 | // lw(HOLE): x2 / SP 75 | lw x3, (4* 6)(sp) 76 | lw x4, (4* 7)(sp) 77 | lw x5, (4* 8)(sp) 78 | lw x6, (4* 9)(sp) 79 | lw x7, (4*10)(sp) 80 | lw x8, (4*11)(sp) 81 | lw x9, (4*12)(sp) 82 | lw x10, (4*13)(sp) 83 | lw x11, (4*14)(sp) 84 | lw x12, (4*15)(sp) 85 | lw x13, (4*16)(sp) 86 | lw x14, (4*17)(sp) 87 | lw x15, (4*18)(sp) 88 | lw x16, (4*19)(sp) 89 | lw x17, (4*20)(sp) 90 | lw x18, (4*21)(sp) 91 | lw x19, (4*22)(sp) 92 | lw x20, (4*23)(sp) 93 | lw x21, (4*24)(sp) 94 | lw x22, (4*25)(sp) 95 | lw x23, (4*26)(sp) 96 | lw x24, (4*27)(sp) 97 | lw x25, (4*28)(sp) 98 | lw x26, (4*29)(sp) 99 | lw x27, (4*30)(sp) 100 | lw x28, (4*31)(sp) 101 | lw x29, (4*32)(sp) 102 | lw x30, (4*33)(sp) 103 | lw x31, (4*34)(sp) 104 | 105 | addi sp, sp, (35*4) 106 | #ifdef EXCEPTION_SP_FROM_MSCRATCH 107 | csrrw sp, mscratch, sp 108 | #endif 109 | mret 110 | 111 | .global exception_syscall 112 | exception_syscall: 113 | ecall 114 | ret 115 | -------------------------------------------------------------------------------- /firmware/arch/riscv/init.c: -------------------------------------------------------------------------------- 1 | #include "csr.h" 2 | #include "exception.h" 3 | #ifdef CONFIG_UARTLITE 4 | #include "uart_lite.h" 5 | #endif 6 | #ifdef CONFIG_IRQCTRL 7 | #include "irq_ctrl.h" 8 | #endif 9 | 10 | #ifdef CONFIG_MALLOC 11 | #include "malloc.h" 12 | #endif 13 | 14 | #ifdef CONFIG_MALLOC 15 | static uint8_t _heap[CONFIG_MALLOC_SIZE]; 16 | #endif 17 | 18 | //----------------------------------------------------------------- 19 | // init: 20 | //----------------------------------------------------------------- 21 | void init(void) 22 | { 23 | #ifdef CONFIG_UARTLITE 24 | // Setup serial port 25 | uartlite_init(CONFIG_UARTLITE_BASE, 0); 26 | 27 | // Register serial driver with printf 28 | printf_register(uartlite_putc); 29 | #endif 30 | 31 | #if defined (CONFIG_MALLOC) 32 | malloc_init(_heap, CONFIG_MALLOC_SIZE, 0, 0); 33 | #endif 34 | 35 | #ifdef CONFIG_IRQCTRL 36 | irqctrl_init(CONFIG_IRQCTRL_BASE); 37 | #endif 38 | } 39 | -------------------------------------------------------------------------------- /firmware/arch/riscv/linker_script.ld: -------------------------------------------------------------------------------- 1 | GROUP("libgcc.a") 2 | 3 | MEMORY 4 | { 5 | sram (rwx) : ORIGIN = BASE_ADDRESS, LENGTH = MEM_SIZE 6 | } 7 | 8 | SECTIONS 9 | { 10 | /* first section is .text which is used for code */ 11 | .text : 12 | { 13 | *(.boot) 14 | KEEP(*(.boot)) 15 | 16 | *(.text .text.*) /* remaining code */ 17 | *(.rodata) /* read-only data (constants) */ 18 | *(.rodata*) 19 | *(.rdata*) 20 | . = ALIGN(4); 21 | } > sram 22 | 23 | /* .data section which is used for initialized data */ 24 | .data : 25 | { 26 | *(.got.plt) *(.got) 27 | *(.shdata) 28 | *(.data .data.* .gnu.linkonce.d.*) 29 | . = ALIGN(16); 30 | *(.lit8) 31 | *(.lit4) 32 | *(.sdata .sdata.* .gnu.linkonce.s.*) 33 | . = ALIGN (8); 34 | *(.ram) 35 | . = ALIGN (8); 36 | _edata = .; 37 | } > sram 38 | 39 | .bss : 40 | { 41 | . = ALIGN(4); 42 | _bss_start = . ; 43 | 44 | *(.bss*) 45 | *(.sbss*) 46 | *(COMMON) 47 | /* Allocate room for stack */ 48 | . = ALIGN(8) ; 49 | . += 4096 ; 50 | _sp = . - 16; 51 | } > sram 52 | 53 | . = ALIGN(4); 54 | _end = . ; 55 | 56 | .payload : 57 | { 58 | *(.payload) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /firmware/arch/riscv/timer.c: -------------------------------------------------------------------------------- 1 | #include "timer.h" 2 | #include "csr.h" 3 | #include 4 | 5 | //----------------------------------------------------------------- 6 | // cpu_timer_get_count: 7 | //----------------------------------------------------------------- 8 | static inline unsigned long cpu_timer_get_count(void) 9 | { 10 | unsigned long value; 11 | asm volatile ("csrr %0, cycle" : "=r" (value) : ); 12 | return value; 13 | } 14 | //-------------------------------------------------------------------------- 15 | // timer_init: 16 | //-------------------------------------------------------------------------- 17 | void timer_init(void) 18 | { 19 | 20 | } 21 | //-------------------------------------------------------------------------- 22 | // timer_sleep: 23 | //-------------------------------------------------------------------------- 24 | void timer_sleep(int timeMs) 25 | { 26 | t_time t = timer_now(); 27 | 28 | while (timer_diff(timer_now(), t) < timeMs) 29 | ; 30 | } 31 | //-------------------------------------------------------------------------- 32 | // timer_now: 33 | //-------------------------------------------------------------------------- 34 | t_time timer_now(void) 35 | { 36 | return cpu_timer_get_count() / CPU_KHZ; 37 | } 38 | //-------------------------------------------------------------------------- 39 | // timer_set_mtimecmp: Non-std mtimecmp support 40 | //-------------------------------------------------------------------------- 41 | void timer_set_mtimecmp(t_time next) 42 | { 43 | csr_write(0x7c0, next); 44 | } 45 | //-------------------------------------------------------------------------- 46 | // timer_get_mtime: 47 | //-------------------------------------------------------------------------- 48 | t_time timer_get_mtime(void) 49 | { 50 | return csr_read(0xc00); 51 | } -------------------------------------------------------------------------------- /firmware/arch/riscv/timer.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIMER_H__ 2 | #define __TIMER_H__ 3 | 4 | //----------------------------------------------------------------- 5 | // Defines: 6 | //----------------------------------------------------------------- 7 | #ifndef CPU_KHZ 8 | #define CPU_KHZ 48000 9 | #endif 10 | 11 | //----------------------------------------------------------------- 12 | // Types 13 | //----------------------------------------------------------------- 14 | typedef unsigned long t_time; 15 | 16 | //----------------------------------------------------------------- 17 | // Prototypes: 18 | //----------------------------------------------------------------- 19 | 20 | // General timer 21 | void timer_init(void); 22 | t_time timer_now(void); 23 | static long timer_diff(t_time a, t_time b) { return (long)(a - b); } 24 | void timer_sleep(int timeMs); 25 | void timer_set_mtimecmp(t_time next); 26 | t_time timer_get_mtime(void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /firmware/drivers/audio/audio.h: -------------------------------------------------------------------------------- 1 | #ifndef __AUDIO_H__ 2 | #define __AUDIO_H__ 3 | 4 | #include 5 | 6 | typedef enum 7 | { 8 | AUDIO_TARGET_I2S, 9 | AUDIO_TARGET_SPDIF, 10 | AUDIO_TARGET_ANALOG, 11 | AUDIO_TARGET_MAX 12 | } tAudioTarget; 13 | 14 | //----------------------------------------------------------------- 15 | // Prototypes: 16 | //----------------------------------------------------------------- 17 | void audio_init(uint32_t base_addr, int irq_num, uint32_t clock_rate, tAudioTarget target); 18 | uint32_t audio_fifo_level(void); 19 | uint32_t audio_fifo_space(void); 20 | void audio_load_samples(uint32_t *p, int length); 21 | void audio_swap_channels(int enable); 22 | void audio_swap_endian(int enable); 23 | void audio_set_volume(int percent); 24 | 25 | #endif // __AUDIO_H__ 26 | -------------------------------------------------------------------------------- /firmware/drivers/fb/fb_dev.c: -------------------------------------------------------------------------------- 1 | #include "fb_dev.h" 2 | 3 | // Driver for frame buffer device: 4 | // https://github.com/ultraembedded/core_dvi_framebuffer 5 | #ifdef CONFIG_FRAMEBUFFER 6 | 7 | //----------------------------------------------------------------- 8 | // Defines 9 | //----------------------------------------------------------------- 10 | #define VIDEO_CONFIG 0x0 11 | 12 | #define VIDEO_CONFIG_X2_MODE 2 13 | #define VIDEO_CONFIG_X2_MODE_SHIFT 2 14 | #define VIDEO_CONFIG_X2_MODE_MASK 0x1 15 | 16 | #define VIDEO_CONFIG_INT_EN_SOF 1 17 | #define VIDEO_CONFIG_INT_EN_SOF_SHIFT 1 18 | #define VIDEO_CONFIG_INT_EN_SOF_MASK 0x1 19 | 20 | #define VIDEO_CONFIG_ENABLE 0 21 | #define VIDEO_CONFIG_ENABLE_SHIFT 0 22 | #define VIDEO_CONFIG_ENABLE_MASK 0x1 23 | 24 | #define VIDEO_STATUS 0x4 25 | #define VIDEO_STATUS_FB_PENDING 31 26 | #define VIDEO_STATUS_FB_PENDING_SHIFT 31 27 | #define VIDEO_STATUS_FB_PENDING_MASK 0x1 28 | 29 | #define VIDEO_STATUS_Y_POS_SHIFT 16 30 | #define VIDEO_STATUS_Y_POS_MASK 0x7fff 31 | 32 | #define VIDEO_STATUS_H_POS_SHIFT 0 33 | #define VIDEO_STATUS_H_POS_MASK 0xffff 34 | 35 | #define VIDEO_FRAME_BUFFER 0x8 36 | #define VIDEO_FRAME_BUFFER_ADDR_SHIFT 8 37 | #define VIDEO_FRAME_BUFFER_ADDR_MASK 0xffffff 38 | 39 | //----------------------------------------------------------------- 40 | // Locals 41 | //----------------------------------------------------------------- 42 | static volatile uint32_t *m_fb; 43 | static int m_fb_width; 44 | static int m_fb_height; 45 | 46 | //----------------------------------------------------------------- 47 | // fbdev_init: Initialise frame buffer peripheral 48 | //----------------------------------------------------------------- 49 | void fbdev_init(uint32_t base_addr, uint32_t frame_buffer, int width, int height, int enable, int x2_mode) 50 | { 51 | m_fb = (volatile uint32_t *)base_addr; 52 | 53 | m_fb_width = width; 54 | m_fb_height = height; 55 | 56 | m_fb[VIDEO_FRAME_BUFFER/4] = frame_buffer; 57 | m_fb[VIDEO_CONFIG/4] = (enable << VIDEO_CONFIG_ENABLE_SHIFT) | 58 | (x2_mode << VIDEO_CONFIG_X2_MODE_SHIFT); 59 | } 60 | //----------------------------------------------------------------- 61 | // fbdev_wait_ready: Wait until frame buffer address update accepted 62 | //----------------------------------------------------------------- 63 | void fbdev_wait_ready(void) 64 | { 65 | while (m_fb[VIDEO_STATUS/4] & (1 << VIDEO_STATUS_FB_PENDING_SHIFT)) 66 | ; 67 | } 68 | //----------------------------------------------------------------- 69 | // fbdev_set_framebuffer: Set new frame buffer address 70 | //----------------------------------------------------------------- 71 | void fbdev_set_framebuffer(uint32_t frame_buffer) 72 | { 73 | fbdev_wait_ready(); 74 | m_fb[VIDEO_FRAME_BUFFER/4] = frame_buffer; 75 | } 76 | //----------------------------------------------------------------- 77 | // fbdev_draw_pixel: Draw pixel 78 | //----------------------------------------------------------------- 79 | void fbdev_draw_pixel(uint16_t *frame, int x, int y, uint16_t colour) 80 | { 81 | int offset = x + (y * m_fb_width); 82 | frame[offset] = colour; 83 | } 84 | //----------------------------------------------------------------- 85 | // fbdev_fill_screen: Fill screen with a particular colour 86 | //----------------------------------------------------------------- 87 | void fbdev_fill_screen(uint16_t *frame, uint16_t value) 88 | { 89 | for (int y=0;y> 3)] & (1 << (~u & 7))) 110 | fbdev_draw_pixel(frame, x + u, y + v, colour); 111 | else 112 | fbdev_draw_pixel(frame, x + u, y + v, bg_colour); 113 | } 114 | } 115 | 116 | #endif 117 | -------------------------------------------------------------------------------- /firmware/drivers/fb/fb_dev.h: -------------------------------------------------------------------------------- 1 | #ifndef __FB_DEV_H__ 2 | #define __FB_DEV_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Defines 8 | //----------------------------------------------------------------- 9 | // 24 bit RGB to 16 bit RGB565 10 | #define RGB565(r,g,b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)) 11 | 12 | //----------------------------------------------------------------- 13 | // Prototypes 14 | //----------------------------------------------------------------- 15 | void fbdev_init(uint32_t base_addr, uint32_t frame_buffer, int width, int height, int enable, int x2_mode); 16 | void fbdev_wait_ready(void); 17 | void fbdev_set_framebuffer(uint32_t frame_buffer); 18 | void fbdev_draw_pixel(uint16_t *frame, int x, int y, uint16_t colour); 19 | void fbdev_fill_screen(uint16_t *frame, uint16_t value); 20 | void fbdev_clear_screen(uint16_t *frame); 21 | void fbdev_draw_bitmap(uint16_t *frame, uint8_t* bitmap, int x, int y, int width, int height, uint16_t colour, uint16_t bg_colour); 22 | 23 | #endif -------------------------------------------------------------------------------- /firmware/drivers/gpio/gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef __GPIO_H__ 2 | #define __GPIO_H__ 3 | 4 | #include 5 | 6 | #ifndef GPIO_BASE 7 | #define GPIO_BASE 0x94000000 8 | #endif 9 | 10 | //----------------------------------------------------------------- 11 | // GPIO Registers 12 | //----------------------------------------------------------------- 13 | #define GPIO_DIRECTION 0x0 14 | #define GPIO_DIRECTION_OUTPUT_SHIFT 0 15 | #define GPIO_DIRECTION_OUTPUT_MASK 0xffffffff 16 | 17 | #define GPIO_INPUT 0x4 18 | #define GPIO_INPUT_VALUE_SHIFT 0 19 | #define GPIO_INPUT_VALUE_MASK 0xffffffff 20 | 21 | #define GPIO_OUTPUT 0x8 22 | #define GPIO_OUTPUT_DATA_SHIFT 0 23 | #define GPIO_OUTPUT_DATA_MASK 0xffffffff 24 | 25 | #define GPIO_OUTPUT_SET 0xc 26 | #define GPIO_OUTPUT_SET_DATA_SHIFT 0 27 | #define GPIO_OUTPUT_SET_DATA_MASK 0xffffffff 28 | 29 | #define GPIO_OUTPUT_CLR 0x10 30 | #define GPIO_OUTPUT_CLR_DATA_SHIFT 0 31 | #define GPIO_OUTPUT_CLR_DATA_MASK 0xffffffff 32 | 33 | #define GPIO_INT_MASK 0x14 34 | #define GPIO_INT_MASK_ENABLE_SHIFT 0 35 | #define GPIO_INT_MASK_ENABLE_MASK 0xffffffff 36 | 37 | #define GPIO_INT_SET 0x18 38 | #define GPIO_INT_SET_SW_IRQ_SHIFT 0 39 | #define GPIO_INT_SET_SW_IRQ_MASK 0xffffffff 40 | 41 | #define GPIO_INT_CLR 0x1c 42 | #define GPIO_INT_CLR_ACK_SHIFT 0 43 | #define GPIO_INT_CLR_ACK_MASK 0xffffffff 44 | 45 | #define GPIO_INT_STATUS 0x20 46 | #define GPIO_INT_STATUS_RAW_SHIFT 0 47 | #define GPIO_INT_STATUS_RAW_MASK 0xffffffff 48 | 49 | #define GPIO_INT_LEVEL 0x24 50 | #define GPIO_INT_LEVEL_ACTIVE_HIGH_SHIFT 0 51 | #define GPIO_INT_LEVEL_ACTIVE_HIGH_MASK 0xffffffff 52 | 53 | #define GPIO_INT_MODE 0x28 54 | #define GPIO_INT_MODE_EDGE_SHIFT 0 55 | #define GPIO_INT_MODE_EDGE_MASK 0xffffffff 56 | 57 | //----------------------------------------------------------------- 58 | // Prototypes: 59 | //----------------------------------------------------------------- 60 | 61 | // Write word to GPIO outputs 62 | static inline void gpio_output_write(uint32_t value) 63 | { 64 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 65 | gpio[GPIO_OUTPUT/4] = value; 66 | } 67 | 68 | // Set (high) specific pins (1 = high, 0 = unchanged) 69 | static inline void gpio_output_set(uint32_t mask) 70 | { 71 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 72 | gpio[GPIO_OUTPUT_SET/4] = mask; 73 | } 74 | 75 | // Clear (low) specific pins (1 = low, 0 = unchanged) 76 | static inline void gpio_output_clr(uint32_t mask) 77 | { 78 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 79 | gpio[GPIO_OUTPUT_CLR/4] = mask; 80 | } 81 | 82 | // Read GPIO inputs 83 | static inline uint32_t gpio_input_read(void) 84 | { 85 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 86 | return gpio[GPIO_INPUT/4]; 87 | } 88 | 89 | // Read specific GPIO pin (0 - 31) 90 | static inline uint32_t gpio_input_bit(int bit) 91 | { 92 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 93 | return (gpio[GPIO_INPUT/4] & (1 << bit)) != 0; 94 | } 95 | 96 | // Configure GPIO direction (1 = output, 0 = input) 97 | static inline void gpio_enable_outputs(uint32_t mask) 98 | { 99 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 100 | gpio[GPIO_DIRECTION/4] = mask; 101 | } 102 | 103 | // Configure GPIO interrupts 104 | static inline void gpio_configure_int(int bit, int enabled, int edge_not_level, int active_high_rising) 105 | { 106 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 107 | uint32_t current; 108 | 109 | // Enable 110 | current = gpio[GPIO_INT_MASK/4]; 111 | if (enabled) 112 | current |= (1 << bit); 113 | else 114 | current &= ~(1 << bit); 115 | gpio[GPIO_INT_MASK/4] = current; 116 | 117 | current = gpio[GPIO_INT_LEVEL/4]; 118 | if (active_high_rising) 119 | current |= (1 << bit); 120 | else 121 | current &= ~(1 << bit); 122 | gpio[GPIO_INT_LEVEL/4] = current; 123 | 124 | current = gpio[GPIO_INT_MODE/4]; 125 | if (edge_not_level) 126 | current |= (1 << bit); 127 | else 128 | current &= ~(1 << bit); 129 | gpio[GPIO_INT_MODE/4] = current; 130 | } 131 | 132 | // Clear bitmap of interrupts 133 | static inline void gpio_interrupt_ack(uint32_t mask) 134 | { 135 | volatile uint32_t * gpio = (volatile uint32_t * )GPIO_BASE; 136 | gpio[GPIO_INT_CLR/4] = mask; 137 | } 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /firmware/drivers/irq/irq_ctrl.c: -------------------------------------------------------------------------------- 1 | #include "irq_ctrl.h" 2 | 3 | #ifdef CONFIG_IRQCTRL 4 | #include "exception.h" 5 | #include "csr.h" 6 | #include "assert.h" 7 | 8 | //----------------------------------------------------------------- 9 | // Defines 10 | //----------------------------------------------------------------- 11 | #define IRQ_ISR 0x0 12 | #define IRQ_ISR_STATUS_SHIFT 0 13 | #define IRQ_ISR_STATUS_MASK 0xf 14 | 15 | #define IRQ_IPR 0x4 16 | #define IRQ_IPR_PENDING_SHIFT 0 17 | #define IRQ_IPR_PENDING_MASK 0xf 18 | 19 | #define IRQ_IER 0x8 20 | #define IRQ_IER_ENABLE_SHIFT 0 21 | #define IRQ_IER_ENABLE_MASK 0xf 22 | 23 | #define IRQ_IAR 0xc 24 | #define IRQ_IAR_ACK_SHIFT 0 25 | #define IRQ_IAR_ACK_MASK 0xf 26 | 27 | #define IRQ_SIE 0x10 28 | #define IRQ_SIE_SET_SHIFT 0 29 | #define IRQ_SIE_SET_MASK 0xf 30 | 31 | #define IRQ_CIE 0x14 32 | #define IRQ_CIE_CLR_SHIFT 0 33 | #define IRQ_CIE_CLR_MASK 0xf 34 | 35 | #define IRQ_IVR 0x18 36 | #define IRQ_IVR_VECTOR_SHIFT 0 37 | #define IRQ_IVR_VECTOR_MASK 0xffffffff 38 | 39 | #define IRQ_MER 0x1c 40 | #define IRQ_MER_ME 0 41 | #define IRQ_MER_ME_SHIFT 0 42 | #define IRQ_MER_ME_MASK 0x1 43 | 44 | //----------------------------------------------------------------- 45 | // RISC-V Superdefs 46 | //----------------------------------------------------------------- 47 | #define IRQ_S_SOFT 1 48 | #define IRQ_M_SOFT 3 49 | #define IRQ_S_TIMER 5 50 | #define IRQ_M_TIMER 7 51 | #define IRQ_S_EXT 9 52 | #define IRQ_M_EXT 11 53 | 54 | //----------------------------------------------------------------- 55 | // Locals 56 | //----------------------------------------------------------------- 57 | static volatile uint32_t *m_irq; 58 | 59 | #define IRQ_MAX 32 60 | static fp_irq_func m_irq_table[IRQ_MAX]; 61 | 62 | //----------------------------------------------------------------- 63 | // irqctrl_handler: Interrupt handler 64 | //----------------------------------------------------------------- 65 | struct irq_context * irqctrl_handler(struct irq_context *ctx) 66 | { 67 | int irq_num = m_irq[IRQ_IVR/4]; 68 | 69 | if (irq_num != -1) 70 | { 71 | assert(m_irq_table[irq_num]); 72 | ctx = (struct irq_context *)m_irq_table[irq_num](ctx, irq_num); 73 | 74 | // Ack IRQ 75 | m_irq[IRQ_IAR/4] = 1 << irq_num; 76 | } 77 | 78 | csr_irq_ack(1 << 11); // M_EXT 79 | return ctx; 80 | } 81 | //----------------------------------------------------------------- 82 | // irqctrl_get_irq: Get highest priority pending IRQ 83 | //----------------------------------------------------------------- 84 | int irqctrl_get_irq(void) 85 | { 86 | return m_irq[IRQ_IVR/4]; 87 | } 88 | //----------------------------------------------------------------- 89 | // irqctrl_enable_irq: Enable IRQ 90 | //----------------------------------------------------------------- 91 | void irqctrl_enable_irq(int irq, int enable) 92 | { 93 | if (enable) 94 | m_irq[IRQ_SIE/4] = (1 << irq); 95 | else 96 | m_irq[IRQ_CIE/4] = (1 << irq); 97 | } 98 | //----------------------------------------------------------------- 99 | // irqctrl_acknowledge: Acknowledge IRQ 100 | //----------------------------------------------------------------- 101 | void irqctrl_acknowledge(int irq) 102 | { 103 | // Ack IRQ 104 | m_irq[IRQ_IAR/4] = 1 << irq; 105 | 106 | csr_irq_ack(1 << 11); // M_EXT 107 | } 108 | //----------------------------------------------------------------- 109 | // irqctrl_sw_int: Generate SW IRQ 110 | //----------------------------------------------------------------- 111 | void irqctrl_sw_int(int irq) 112 | { 113 | m_irq[IRQ_ISR/4] = (1 << irq); 114 | } 115 | //----------------------------------------------------------------- 116 | // irqctrl_set_handler: Setup IRQ handler 117 | //----------------------------------------------------------------- 118 | void irqctrl_set_handler(int irq, fp_irq_func handler) 119 | { 120 | m_irq_table[irq] = handler; 121 | } 122 | //----------------------------------------------------------------- 123 | // irqctrl_init: Initialise IRQ peripheral 124 | //----------------------------------------------------------------- 125 | void irqctrl_init(uint32_t base_addr) 126 | { 127 | uint32_t cfg = 0; 128 | m_irq = (volatile uint32_t *)base_addr; 129 | 130 | // Interrupt off 131 | m_irq[IRQ_CIE/4] = ~0; 132 | 133 | // Interrupts ack'd 134 | m_irq[IRQ_IAR/4] = ~0; 135 | 136 | // Register interrupt handler 137 | exception_set_irq_handler(irqctrl_handler); 138 | 139 | // Reset current state 140 | csr_irq_ack(~0); 141 | 142 | csr_set_irq_enable(); 143 | 144 | // Enable external interrupts 145 | csr_set_irq_mask(1 << IRQ_M_EXT); 146 | 147 | // Global interrupt enable 148 | m_irq[IRQ_MER/4] = (1 << IRQ_MER_ME_SHIFT); 149 | } 150 | #endif 151 | -------------------------------------------------------------------------------- /firmware/drivers/irq/irq_ctrl.h: -------------------------------------------------------------------------------- 1 | #ifndef __IRQ_CTRL_H__ 2 | #define __IRQ_CTRL_H__ 3 | 4 | #include 5 | #include "exception.h" 6 | 7 | //----------------------------------------------------------------- 8 | // Types 9 | //----------------------------------------------------------------- 10 | typedef void* (*fp_irq_func)(void *ctx, int irq); 11 | 12 | //----------------------------------------------------------------- 13 | // Prototypes 14 | //----------------------------------------------------------------- 15 | void irqctrl_init(uint32_t base_addr); 16 | int irqctrl_get_irq(void); 17 | void irqctrl_enable_irq(int irq, int enable); 18 | void irqctrl_set_handler(int irq, fp_irq_func handler); 19 | void irqctrl_acknowledge(int irq); 20 | void irqctrl_sw_int(int irq); 21 | 22 | struct irq_context * irqctrl_handler(struct irq_context *ctx); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /firmware/drivers/jpeg/jpeg_hw.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "assert.h" 3 | 4 | #ifdef CONFIG_JPEG_HW 5 | #include "jpeg_hw.h" 6 | 7 | #ifndef CONFIG_JPEG_HW_BASE 8 | #define CONFIG_JPEG_HW_BASE 0x97000000 9 | #endif 10 | 11 | //----------------------------------------------------------------- 12 | // Registers 13 | //----------------------------------------------------------------- 14 | #define JPEG_CTRL 0x0 15 | #define JPEG_CTRL_START 31 16 | #define JPEG_CTRL_START_SHIFT 31 17 | #define JPEG_CTRL_START_MASK 0x1 18 | 19 | #define JPEG_CTRL_ABORT 30 20 | #define JPEG_CTRL_ABORT_SHIFT 30 21 | #define JPEG_CTRL_ABORT_MASK 0x1 22 | 23 | #define JPEG_CTRL_LENGTH_SHIFT 0 24 | #define JPEG_CTRL_LENGTH_MASK 0xffffff 25 | 26 | #define JPEG_STATUS 0x4 27 | #define JPEG_STATUS_UNDERRUN 0 28 | #define JPEG_STATUS_UNDERRUN_SHIFT 0 29 | #define JPEG_STATUS_UNDERRUN_MASK 0x1 30 | 31 | #define JPEG_STATUS_OVERFLOW 0 32 | #define JPEG_STATUS_OVERFLOW_SHIFT 0 33 | #define JPEG_STATUS_OVERFLOW_MASK 0x1 34 | 35 | #define JPEG_STATUS_BUSY 0 36 | #define JPEG_STATUS_BUSY_SHIFT 0 37 | #define JPEG_STATUS_BUSY_MASK 0x1 38 | 39 | #define JPEG_SRC 0x8 40 | #define JPEG_SRC_ADDR_SHIFT 0 41 | #define JPEG_SRC_ADDR_MASK 0xffffffff 42 | 43 | #define JPEG_DST 0xc 44 | #define JPEG_DST_ADDR_SHIFT 0 45 | #define JPEG_DST_ADDR_MASK 0xffffffff 46 | 47 | //----------------------------------------------------------------- 48 | // HW access 49 | //----------------------------------------------------------------- 50 | static inline void jpeg_hw_write(uint32_t addr, uint32_t value) 51 | { 52 | volatile uint32_t * cfg = (volatile uint32_t * )CONFIG_JPEG_HW_BASE; 53 | cfg[addr/4] = value; 54 | } 55 | static inline uint32_t jpeg_hw_read(uint32_t addr) 56 | { 57 | volatile uint32_t * cfg = (volatile uint32_t * )CONFIG_JPEG_HW_BASE; 58 | return cfg[addr/4]; 59 | } 60 | //----------------------------------------------------------------- 61 | // jpeg_hw_reset: Reset HW decoder 62 | //----------------------------------------------------------------- 63 | void jpeg_hw_reset(void) 64 | { 65 | // Reset JPEG HW state 66 | jpeg_hw_write(JPEG_CTRL, (1 << JPEG_CTRL_ABORT_SHIFT)); 67 | } 68 | //----------------------------------------------------------------- 69 | // jpeg_hw_start: Start HW decode 70 | //----------------------------------------------------------------- 71 | void jpeg_hw_start(uint32_t src_addr, uint32_t dst_addr, uint32_t image_size) 72 | { 73 | // Reset JPEG HW state 74 | jpeg_hw_write(JPEG_CTRL, (1 << JPEG_CTRL_ABORT_SHIFT)); 75 | 76 | // Set compressed source buffer details 77 | assert((src_addr & 0x1f) == 0); 78 | jpeg_hw_write(JPEG_SRC, src_addr); 79 | 80 | // Set uncompressed target details 81 | assert((dst_addr & 0x3) == 0); 82 | jpeg_hw_write(JPEG_DST, dst_addr); 83 | 84 | // Go 85 | jpeg_hw_write(JPEG_CTRL, (1 << JPEG_CTRL_START_SHIFT) | image_size); 86 | } 87 | //----------------------------------------------------------------- 88 | // jpeg_hw_start: Start HW decode 89 | //----------------------------------------------------------------- 90 | int jpeg_hw_busy(void) 91 | { 92 | return (jpeg_hw_read(JPEG_STATUS) & (1 << JPEG_STATUS_BUSY_SHIFT)) != 0; 93 | } 94 | //----------------------------------------------------------------- 95 | // jpeg_hw_decode: Blocking JPEG decode 96 | //----------------------------------------------------------------- 97 | void jpeg_hw_decode(uint32_t src_addr, uint32_t dst_addr, uint32_t image_size) 98 | { 99 | jpeg_hw_start(src_addr, dst_addr, image_size); 100 | while (jpeg_hw_busy()) 101 | ; 102 | } 103 | #endif -------------------------------------------------------------------------------- /firmware/drivers/jpeg/jpeg_hw.h: -------------------------------------------------------------------------------- 1 | #ifndef __JPEG_HW_H__ 2 | #define __JPEG_HW_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | void jpeg_hw_reset(void); 10 | void jpeg_hw_start(uint32_t src_addr, uint32_t dst_addr, uint32_t image_size); 11 | int jpeg_hw_busy(void); 12 | void jpeg_hw_decode(uint32_t src_addr, uint32_t dst_addr, uint32_t image_size); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /firmware/drivers/sd/sd.h: -------------------------------------------------------------------------------- 1 | #ifndef __SD_H__ 2 | #define __SD_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes: 8 | //----------------------------------------------------------------- 9 | 10 | // sd_init: Return 0 on success, non zero of failure 11 | int sd_init(void); 12 | 13 | // sd_writesector: Return 1 on success, 0 on failure 14 | int sd_writesector(uint32_t sector, uint8_t *buffer, uint32_t sector_count); 15 | 16 | // sd_readsector: Return 1 on success, 0 on failure 17 | int sd_readsector(uint32_t sector, uint8_t *buffer, uint32_t sector_count); 18 | 19 | // Async IO reads 20 | int sd_readsector_dma_start(uint32_t start_block, uint8_t *buffer, uint32_t sector_count); 21 | int sd_readsector_dma_end(void); 22 | void sd_readsector_dma_reset(void); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /firmware/drivers/uart/uart_lite.c: -------------------------------------------------------------------------------- 1 | #include "uart_lite.h" 2 | 3 | #ifdef CONFIG_UARTLITE 4 | 5 | //----------------------------------------------------------------- 6 | // Defines 7 | //----------------------------------------------------------------- 8 | #define ULITE_RX 0x0 9 | #define ULITE_RX_DATA_SHIFT 0 10 | #define ULITE_RX_DATA_MASK 0xff 11 | 12 | #define ULITE_TX 0x4 13 | #define ULITE_TX_DATA_SHIFT 0 14 | #define ULITE_TX_DATA_MASK 0xff 15 | 16 | #define ULITE_STATUS 0x8 17 | #define ULITE_STATUS_IE 4 18 | #define ULITE_STATUS_IE_SHIFT 4 19 | #define ULITE_STATUS_IE_MASK 0x1 20 | 21 | #define ULITE_STATUS_TXFULL 3 22 | #define ULITE_STATUS_TXFULL_SHIFT 3 23 | #define ULITE_STATUS_TXFULL_MASK 0x1 24 | 25 | #define ULITE_STATUS_TXEMPTY 2 26 | #define ULITE_STATUS_TXEMPTY_SHIFT 2 27 | #define ULITE_STATUS_TXEMPTY_MASK 0x1 28 | 29 | #define ULITE_STATUS_RXFULL 1 30 | #define ULITE_STATUS_RXFULL_SHIFT 1 31 | #define ULITE_STATUS_RXFULL_MASK 0x1 32 | 33 | #define ULITE_STATUS_RXVALID 0 34 | #define ULITE_STATUS_RXVALID_SHIFT 0 35 | #define ULITE_STATUS_RXVALID_MASK 0x1 36 | 37 | #define ULITE_CONTROL 0xc 38 | #define ULITE_CONTROL_IE 4 39 | #define ULITE_CONTROL_IE_SHIFT 4 40 | #define ULITE_CONTROL_IE_MASK 0x1 41 | 42 | #define ULITE_CONTROL_RST_RX 1 43 | #define ULITE_CONTROL_RST_RX_SHIFT 1 44 | #define ULITE_CONTROL_RST_RX_MASK 0x1 45 | 46 | #define ULITE_CONTROL_RST_TX 0 47 | #define ULITE_CONTROL_RST_TX_SHIFT 0 48 | #define ULITE_CONTROL_RST_TX_MASK 0x1 49 | 50 | //----------------------------------------------------------------- 51 | // Locals 52 | //----------------------------------------------------------------- 53 | static volatile uint32_t *m_uart; 54 | 55 | //----------------------------------------------------------------- 56 | // uartlite_init: Initialise UART peripheral 57 | //----------------------------------------------------------------- 58 | void uartlite_init(uint32_t base_addr, uint32_t baud_rate) 59 | { 60 | uint32_t cfg = 0; 61 | m_uart = (volatile uint32_t *)base_addr; 62 | 63 | // Soft reset 64 | cfg += (1 << ULITE_CONTROL_RST_RX_SHIFT); 65 | cfg += (1 << ULITE_CONTROL_RST_TX_SHIFT); 66 | cfg += (1 << ULITE_CONTROL_IE_SHIFT); 67 | 68 | m_uart[ULITE_CONTROL/4] = cfg; 69 | } 70 | //----------------------------------------------------------------- 71 | // uartlite_putc: Polled putchar 72 | //----------------------------------------------------------------- 73 | int uartlite_putc(char c) 74 | { 75 | // While TX FIFO full 76 | while (m_uart[ULITE_STATUS/4] & (1 << ULITE_STATUS_TXFULL_SHIFT)) 77 | ; 78 | 79 | m_uart[ULITE_TX/4] = c; 80 | 81 | return 0; 82 | } 83 | //----------------------------------------------------------------- 84 | // uartlite_haschar: 85 | //----------------------------------------------------------------- 86 | int uartlite_haschar(void) 87 | { 88 | return (m_uart[ULITE_STATUS/4] & (1 << ULITE_STATUS_RXVALID_SHIFT)) != 0; 89 | } 90 | //----------------------------------------------------------------- 91 | // uartlite_getchar: Read character from UART 92 | //----------------------------------------------------------------- 93 | int uartlite_getchar(void) 94 | { 95 | if (uartlite_haschar()) 96 | return (uint8_t)m_uart[ULITE_RX/4]; 97 | else 98 | return -1; 99 | } 100 | #ifdef CONFIG_UARTLITE_CONSOLE 101 | //----------------------------------------------------------------- 102 | // console_init: 103 | //----------------------------------------------------------------- 104 | void console_init(uint32_t baud) 105 | { 106 | uartlite_init(CONFIG_UARTLITE_BASE, baud); 107 | } 108 | //----------------------------------------------------------------- 109 | // console_putchar: 110 | //----------------------------------------------------------------- 111 | void console_putchar(int ch) 112 | { 113 | uartlite_putc(ch); 114 | } 115 | //----------------------------------------------------------------- 116 | // console_getchar: Get input or return -1 if none available 117 | //----------------------------------------------------------------- 118 | int console_getchar(int ch) 119 | { 120 | return uartlite_getchar(); 121 | } 122 | #endif 123 | #endif 124 | -------------------------------------------------------------------------------- /firmware/drivers/uart/uart_lite.h: -------------------------------------------------------------------------------- 1 | #ifndef __UART_LITE_H__ 2 | #define __UART_LITE_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Prototypes 8 | //----------------------------------------------------------------- 9 | void uartlite_init(uint32_t base_addr, uint32_t baud_rate); 10 | int uartlite_putc(char c); 11 | int uartlite_haschar(void); 12 | int uartlite_getchar(void); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /firmware/lib/_string.h: -------------------------------------------------------------------------------- 1 | #ifndef __LIB_STRING_H__ 2 | #define __LIB_STRING_H__ 3 | 4 | #ifndef LIBSTD_SIZE_T 5 | #define LIBSTD_SIZE_T 6 | #ifdef LIBSTD_SIZE_T_IS_LONG 7 | typedef unsigned long size_t; 8 | #else 9 | typedef unsigned int size_t; 10 | #endif 11 | #endif 12 | 13 | typedef unsigned int size_t; 14 | 15 | int strcmp(const char* s1, const char* s2); 16 | int strncmp(const char * s1, const char * s2, size_t n); 17 | 18 | size_t strlen(const char * str); 19 | size_t strnlen(const char * str, size_t n); 20 | 21 | char * strcpy(char * dst, const char * src); 22 | char * strncpy(char * dst, const char * src, size_t n); 23 | 24 | size_t strspn(const char *s1, const char *s2); 25 | char * strpbrk(const char *s1, const char *s2); 26 | char * strtok(char *s1, const char *delimit); 27 | 28 | char * strrchr(const char *cp, int ch); 29 | 30 | char * itoa(int n, char *s, int base); 31 | 32 | char *strcat(char *dst, const char *src); 33 | char *strncat(char *s1, const char *s2, size_t count); 34 | 35 | int toupper(int ch); 36 | int tolower(int ch); 37 | 38 | int atoi(const char *str); 39 | int atoi_hex(const char *str); 40 | 41 | void *memset(void *p, int c, size_t n); 42 | int memcmp(const void *dst, const void *src, size_t n); 43 | void *memcpy(void *dst, const void *src, size_t n); 44 | void *memccpy(void *dst, const void *src, int c, size_t count); 45 | int memicmp(const void *buf1, const void *buf2, size_t count); 46 | 47 | #endif // __LIB_STRING_H__ 48 | -------------------------------------------------------------------------------- /firmware/lib/atoi.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // atoi: 9 | //----------------------------------------------------------------- 10 | int atoi(const char *str) 11 | { 12 | unsigned int val = 0; 13 | 14 | while ('0' <= *str && *str <= '9') 15 | { 16 | val *= 10; 17 | val += *str++ - '0'; 18 | } 19 | 20 | return (int)val; 21 | } 22 | //----------------------------------------------------------------- 23 | // atoi_hex: 24 | //----------------------------------------------------------------- 25 | int atoi_hex(const char *str) 26 | { 27 | unsigned int sum = 0; 28 | unsigned int leftshift = 0; 29 | char *s = (char*)str; 30 | char c; 31 | 32 | // Find the end 33 | while (*s) 34 | s++; 35 | 36 | // Backwards through the string 37 | while(s != str) 38 | { 39 | s--; 40 | c = *s; 41 | 42 | if((c >= '0') && (c <= '9')) 43 | sum += (c-'0') << leftshift; 44 | else if((c >= 'A') && (c <= 'F')) 45 | sum += (c-'A'+10) << leftshift; 46 | else if((c >= 'a') && (c <= 'f')) 47 | sum += (c-'a'+10) << leftshift; 48 | else 49 | break; 50 | 51 | leftshift+=4; 52 | } 53 | 54 | return (int)sum; 55 | } 56 | -------------------------------------------------------------------------------- /firmware/lib/bcmp.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // bcmp: 9 | //----------------------------------------------------------------- 10 | #ifdef BCMP_LEGACY 11 | int bcmp(const void *s1, const void *s2, int n) 12 | #else 13 | int bcmp(const void *s1, const void *s2, size_t n) 14 | #endif 15 | { 16 | return memcmp(s1, s2, n); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /firmware/lib/isalpha.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // isupper: 9 | //----------------------------------------------------------------- 10 | int isupper(int c) 11 | { 12 | if(c >= 'A' && c <= 'Z') 13 | return 1; 14 | else 15 | return 0; 16 | } 17 | //----------------------------------------------------------------- 18 | // isalpha: 19 | //----------------------------------------------------------------- 20 | int isalpha(int c) 21 | { 22 | if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) 23 | return 1; 24 | else 25 | return 0; 26 | } 27 | //----------------------------------------------------------------- 28 | // isdigit: 29 | //----------------------------------------------------------------- 30 | int isdigit(int c) 31 | { 32 | if(c >= '0' && c <= '9') 33 | return 1; 34 | else 35 | return 0; 36 | } 37 | //----------------------------------------------------------------- 38 | // isspace: 39 | //----------------------------------------------------------------- 40 | int isspace(int c) 41 | { 42 | if (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v') 43 | return 1; 44 | else 45 | return 0; 46 | } 47 | //----------------------------------------------------------------- 48 | // isalnum: 49 | //----------------------------------------------------------------- 50 | int isalnum(int c) 51 | { 52 | if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) 53 | return 1; 54 | else 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /firmware/lib/itoa.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // reverse: reverse string s in place 9 | //----------------------------------------------------------------- 10 | static void reverse(char s[]) 11 | { 12 | int i, j; 13 | char c; 14 | 15 | for (i = 0, j = strlen(s)-1; i 0); 38 | 39 | if (sign < 0) 40 | s[i++] = '-'; 41 | 42 | s[i] = '\0'; 43 | reverse(s); 44 | 45 | return s; 46 | } 47 | -------------------------------------------------------------------------------- /firmware/lib/malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef __MALLOC_H__ 2 | #define __MALLOC_H__ 3 | 4 | //----------------------------------------------------------------- 5 | // Types: 6 | //----------------------------------------------------------------- 7 | #ifndef LIBSTD_SIZE_T 8 | #define LIBSTD_SIZE_T 9 | #ifdef LIBSTD_SIZE_T_IS_LONG 10 | typedef unsigned long size_t; 11 | #else 12 | typedef unsigned int size_t; 13 | #endif 14 | #endif 15 | 16 | //----------------------------------------------------------------- 17 | // Prototypes 18 | //----------------------------------------------------------------- 19 | void malloc_init( void *heap, size_t len, int (*fn_lock)(void), void (*fn_unlock)(int l) ); 20 | void* malloc( size_t size ); 21 | void free( void *ptr ); 22 | void* calloc( size_t size ); 23 | size_t malloc_largest_free_size(void); 24 | size_t malloc_total_free(void); 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /firmware/lib/memchr.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // memchr: 9 | //----------------------------------------------------------------- 10 | #ifdef MEMCHAR_LEGACY 11 | void * memchr(const void *s, unsigned char c, int n) 12 | #else 13 | void * memchr(const void *s, int c, size_t n) 14 | #endif 15 | { 16 | if (n != 0) 17 | { 18 | const unsigned char *p = (const unsigned char*)s; 19 | 20 | do 21 | { 22 | if (*p++ == c) 23 | return ((void *)(p - 1)); 24 | } 25 | while (--n != 0); 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /firmware/lib/memcmp.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #include 6 | #endif 7 | 8 | //----------------------------------------------------------------- 9 | // memcmp: 10 | //----------------------------------------------------------------- 11 | int memcmp(const void *dst, const void *src, size_t n) 12 | { 13 | if (!n) return 0; 14 | 15 | while (--n && *(char *) dst == *(char *) src) 16 | { 17 | dst = (char *) dst + 1; 18 | src = (char *) src + 1; 19 | } 20 | 21 | return *((unsigned char *) dst) - *((unsigned char *) src); 22 | } 23 | //----------------------------------------------------------------- 24 | // memicmp: 25 | //----------------------------------------------------------------- 26 | int memicmp(const void *buf1, const void *buf2, size_t count) 27 | { 28 | int f = 0, l = 0; 29 | const unsigned char *dst = (const unsigned char*)buf1; 30 | const unsigned char *src = (const unsigned char*)buf2; 31 | 32 | while (count-- && f == l) 33 | { 34 | f = tolower(*dst++); 35 | l = tolower(*src++); 36 | } 37 | 38 | return f - l; 39 | } 40 | -------------------------------------------------------------------------------- /firmware/lib/memcpy.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // memcpy: 9 | //----------------------------------------------------------------- 10 | void *memcpy(void *dst, const void *src, size_t n) 11 | { 12 | void *ret = dst; 13 | 14 | if (sizeof(unsigned long) == 4 && (n > 4) && (((unsigned long)dst) & 3) == 0 && (((unsigned long)src) & 3) == 0) 15 | { 16 | while (n >= 4) 17 | { 18 | *(unsigned long *)dst = *(unsigned long *)src; 19 | dst = (char *) dst + 4; 20 | src = (char *) src + 4; 21 | n -= 4; 22 | } 23 | } 24 | 25 | while (n--) 26 | { 27 | *(char *)dst = *(char *)src; 28 | dst = (char *) dst + 1; 29 | src = (char *) src + 1; 30 | } 31 | 32 | return ret; 33 | } 34 | //----------------------------------------------------------------- 35 | // memccpy: 36 | //----------------------------------------------------------------- 37 | void *memccpy(void *dst, const void *src, int c, size_t count) 38 | { 39 | while (count && (*((char *) (dst = (char *) dst + 1) - 1) = 40 | *((char *)(src = (char *) src + 1) - 1)) != (char) c) 41 | count--; 42 | 43 | return count ? dst : 0; 44 | } 45 | -------------------------------------------------------------------------------- /firmware/lib/memmove.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // memmove: 9 | //----------------------------------------------------------------- 10 | void *memmove(void *v_dst, const void *v_src, size_t length) 11 | { 12 | char *src = (char *)v_src; 13 | char *dst = (char *)v_dst; 14 | unsigned int *src32 = (unsigned int *)v_src; 15 | unsigned int *dst32 = (unsigned int *)v_dst; 16 | 17 | // No need to copy if src = dst or no length 18 | if (!length || v_src == v_dst) 19 | return v_dst; 20 | 21 | // Word aligned source & dest? 22 | if ((((unsigned long)dst & 3) == 0) && (((unsigned long)src & 3) == 0) && (length >= 4)) 23 | { 24 | // How many full words can be copied? 25 | unsigned int len32 = length >> 2; 26 | 27 | // Move from lower address to higher address 28 | if (src < dst) 29 | { 30 | // Copy from end 31 | for (src32 += len32, dst32 += len32; len32; --len32) 32 | *--dst32 = *--src32; 33 | 34 | src+= (length & ~3); 35 | dst+= (length & ~3); 36 | } 37 | // Move from higher address to lower address 38 | else 39 | { 40 | // Copy from start 41 | for (; len32; --len32) 42 | *dst32++ = *src32++; 43 | 44 | src = (char *)src32; 45 | dst = (char *)dst32; 46 | } 47 | 48 | // There might be some bytes left over 49 | length -= (length & ~3); 50 | } 51 | 52 | // Byte copy if not aligned (or odd length) 53 | if (length) 54 | { 55 | // Move from lower address to higher address 56 | if (src < dst) 57 | { 58 | // Copy from end 59 | for (src += length, dst += length; length; --length) 60 | *--dst = *--src; 61 | } 62 | // Move from higher address to lower address 63 | else 64 | { 65 | // Copy from start 66 | for (; length; --length) 67 | *dst++ = *src++; 68 | } 69 | } 70 | 71 | return v_dst; 72 | } -------------------------------------------------------------------------------- /firmware/lib/memset.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // memset: 9 | //----------------------------------------------------------------- 10 | void *memset(void *p, int c, size_t n) 11 | { 12 | char *pb = (char *) p; 13 | char *pbend = pb + n; 14 | 15 | while (pb != pbend) 16 | *pb++ = c; 17 | return p; 18 | } 19 | -------------------------------------------------------------------------------- /firmware/lib/printf.h: -------------------------------------------------------------------------------- 1 | #ifndef __PRINTF_H__ 2 | #define __PRINTF_H__ 3 | 4 | #include 5 | 6 | //----------------------------------------------------------------- 7 | // Types: 8 | //----------------------------------------------------------------- 9 | typedef int (*FP_OUTCHAR)(char c); 10 | 11 | #ifndef LIBSTD_SIZE_T 12 | #define LIBSTD_SIZE_T 13 | #ifdef LIBSTD_SIZE_T_IS_LONG 14 | typedef unsigned long size_t; 15 | #else 16 | typedef unsigned int size_t; 17 | #endif 18 | #endif 19 | 20 | //----------------------------------------------------------------- 21 | // Structures 22 | //----------------------------------------------------------------- 23 | struct vbuf 24 | { 25 | FP_OUTCHAR function; 26 | char * buffer; 27 | int offset; 28 | int max_length; 29 | }; 30 | 31 | //----------------------------------------------------------------- 32 | // Prototypes: 33 | //----------------------------------------------------------------- 34 | int printf(const char* ctrl1, ... ); 35 | void printf_register(FP_OUTCHAR f); 36 | int vsprintf(char *s, const char *format, va_list arg); 37 | int vsnprintf(char *s, size_t maxlen, const char *format, va_list arg); 38 | int sprintf(char *s, const char *format, ...); 39 | int snprintf(char *s, size_t maxlen, const char *format, ...); 40 | int vbuf_printf(struct vbuf *buf, const char* ctrl1, va_list argp); 41 | 42 | #define PRINTF printf 43 | 44 | #endif // __PRINTF_H__ 45 | -------------------------------------------------------------------------------- /firmware/lib/rindex.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // rindex: 9 | //----------------------------------------------------------------- 10 | char *rindex(const char *s, int c) 11 | { 12 | char *it = 0; 13 | 14 | while (1) 15 | { 16 | if (*s == c) 17 | it = (char *)s; 18 | if (*s == 0) 19 | return it; 20 | s++; 21 | } 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /firmware/lib/stpcpy.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | char * stpcpy(char * dst, const char * src) 8 | { 9 | const size_t length = strlen(src); 10 | memcpy(dst, src, length + 1); 11 | return dst + length; 12 | } -------------------------------------------------------------------------------- /firmware/lib/strcat.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // strcat: 9 | //----------------------------------------------------------------- 10 | char *strcat(char *dst, const char *src) 11 | { 12 | char *cp = dst; 13 | while (*cp) 14 | cp++; 15 | while (*cp++ = *src++); 16 | return dst; 17 | } 18 | //----------------------------------------------------------------- 19 | // strncat: 20 | //----------------------------------------------------------------- 21 | char *strncat(char *s1, const char *s2, size_t count) 22 | { 23 | char *start = s1; 24 | 25 | while (*s1++); 26 | 27 | s1--; 28 | 29 | while (count--) 30 | if (!(*s1++ = *s2++)) 31 | return start; 32 | 33 | *s1 = '\0'; 34 | return start; 35 | } 36 | -------------------------------------------------------------------------------- /firmware/lib/strcmp.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #include 6 | #endif 7 | 8 | //----------------------------------------------------------------- 9 | // strcmp: 10 | //----------------------------------------------------------------- 11 | #ifndef CONFIG_HAS_OPTIMISED_STRCMP 12 | int strcmp(const char* s1, const char* s2) 13 | { 14 | while(*s1 == *s2) 15 | { 16 | if(*s1 == 0) 17 | return 0; 18 | 19 | s1 ++; 20 | s2 ++; 21 | } 22 | 23 | return *s1 - *s2; 24 | } 25 | #endif 26 | //----------------------------------------------------------------- 27 | // strncmp: 28 | //----------------------------------------------------------------- 29 | int strncmp(const char * s1, const char * s2, size_t n) 30 | { 31 | if(n == 0) 32 | return 0; 33 | 34 | do 35 | { 36 | if(*s1 != *s2 ++) 37 | return *s1 - *--s2; 38 | if(*s1++ == 0) 39 | break; 40 | } 41 | while (-- n != 0); 42 | 43 | return 0; 44 | } 45 | //----------------------------------------------------------------- 46 | // strcasecmp: 47 | //----------------------------------------------------------------- 48 | int strcasecmp(const char* s1, const char* s2) 49 | { 50 | while(tolower(*s1) == tolower(*s2)) 51 | { 52 | if(*s1 == 0) 53 | return 0; 54 | 55 | s1 ++; 56 | s2 ++; 57 | } 58 | 59 | return tolower(*s1) - tolower(*s2); 60 | } 61 | //----------------------------------------------------------------- 62 | // strncasecmp: 63 | //----------------------------------------------------------------- 64 | int strncasecmp(const char * s1, const char * s2, size_t n) 65 | { 66 | if(n == 0) 67 | return 0; 68 | 69 | do 70 | { 71 | if(tolower(*s1) != tolower(*s2++)) 72 | return tolower(*s1) - tolower(*--s2); 73 | if(*s1++ == 0) 74 | break; 75 | } 76 | while (-- n != 0); 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /firmware/lib/strcpy.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // strcpy: 9 | //----------------------------------------------------------------- 10 | char * strcpy(char * dst, const char * src) 11 | { 12 | char *start = dst; 13 | 14 | while(*dst++ = *src++) 15 | ; 16 | 17 | return start; 18 | } 19 | //----------------------------------------------------------------- 20 | // strncpy: 21 | //----------------------------------------------------------------- 22 | char * strncpy(char * dst, const char * src, size_t n) 23 | { 24 | if(n != 0) 25 | { 26 | char * d = dst; 27 | const char * s = src; 28 | 29 | do 30 | { 31 | if((*d ++ = *s ++) == 0) 32 | { 33 | while (-- n != 0) *d ++ = 0; 34 | break; 35 | } 36 | } 37 | while(-- n != 0); 38 | } 39 | 40 | return dst; 41 | } 42 | -------------------------------------------------------------------------------- /firmware/lib/strlen.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // strlen: 9 | //----------------------------------------------------------------- 10 | size_t strlen(const char * str) 11 | { 12 | const char * s; 13 | 14 | if(!str) 15 | return 0; 16 | 17 | for(s = str; *s; ++ s) 18 | ; 19 | 20 | return s - str; 21 | } 22 | //----------------------------------------------------------------- 23 | // strnlen: 24 | //----------------------------------------------------------------- 25 | size_t strnlen(const char * str, size_t n) 26 | { 27 | const char * s; 28 | 29 | if(n == 0 || !str) 30 | return 0; 31 | 32 | for(s = str; *s && n; ++ s, -- n) 33 | ; 34 | 35 | return s - str; 36 | } 37 | -------------------------------------------------------------------------------- /firmware/lib/strpbrk.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // strpbrk: Find the first occurrence in s1 of a character in s2 9 | //----------------------------------------------------------------- 10 | char * strpbrk(const char* s1, const char* s2) 11 | { 12 | const char *s; 13 | int c, sc; 14 | 15 | while ((c = *s1++) != 0) 16 | { 17 | for (s = s2; (sc = *s++) != 0; ) 18 | if (sc == c) 19 | return ((char *)(s1 - 1)); 20 | } 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /firmware/lib/strrchr.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // strrchr: 9 | //----------------------------------------------------------------- 10 | char * strrchr(const char *cp, int ch) 11 | { 12 | char *save; 13 | char c; 14 | 15 | for (save = (char *) 0; (c = *cp); cp++) 16 | { 17 | if (c == ch) 18 | save = (char *) cp; 19 | } 20 | 21 | return save; 22 | } 23 | //----------------------------------------------------------------- 24 | // strrchr: 25 | //----------------------------------------------------------------- 26 | char *strchr(const char *s, int c) 27 | { 28 | do 29 | { 30 | if (*s == c) 31 | return (char*)s; 32 | } 33 | while (*s++); 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /firmware/lib/strtok.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // strspn: 9 | //----------------------------------------------------------------- 10 | size_t strspn(const char *s1, const char *s2) 11 | { 12 | const char *s = s1; 13 | const char *c; 14 | 15 | while (*s1) 16 | { 17 | for (c = s2; *c; c++) 18 | if (*s1 == *c) 19 | break; 20 | 21 | if (*c == '\0') 22 | break; 23 | s1++; 24 | } 25 | 26 | return s1 - s; 27 | } 28 | //----------------------------------------------------------------- 29 | // strtok: 30 | //----------------------------------------------------------------- 31 | char * strtok(char *s1, const char *delimit) 32 | { 33 | // WARNING: Unsafe shared static! 34 | static char *lastToken = 0; 35 | char *tmp; 36 | 37 | if ( !s1 ) 38 | { 39 | s1 = lastToken; 40 | if (!s1) 41 | return 0; 42 | } 43 | else 44 | s1 += strspn(s1, delimit); 45 | 46 | tmp = strpbrk(s1, delimit); 47 | if (tmp) 48 | { 49 | *tmp = '\0'; 50 | lastToken = tmp + 1; 51 | } 52 | else 53 | lastToken = 0; 54 | 55 | return s1; 56 | } 57 | -------------------------------------------------------------------------------- /firmware/lib/tolower.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // tolower: 9 | //----------------------------------------------------------------- 10 | int tolower(int ch) 11 | { 12 | if ( (unsigned int)(ch - 'A') < 26u ) 13 | ch += 'a' - 'A'; 14 | return ch; 15 | } 16 | -------------------------------------------------------------------------------- /firmware/lib/toupper.c: -------------------------------------------------------------------------------- 1 | #ifdef CONFIG_USE_LOCAL_STRING_H 2 | #include "_string.h" 3 | #else 4 | #include 5 | #endif 6 | 7 | //----------------------------------------------------------------- 8 | // toupper: 9 | //----------------------------------------------------------------- 10 | int toupper(int ch) 11 | { 12 | if ( (unsigned int)(ch - 'a') < 26 ) 13 | ch += 'A' - 'a'; 14 | 15 | return ch; 16 | } 17 | -------------------------------------------------------------------------------- /firmware/make/makefile.exe: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Inputs 3 | ############################################################################### 4 | # SRC_DIR 5 | SRC_DIR ?= . 6 | # INCLUDE_PATH 7 | # TARGET 8 | TARGET ?= target 9 | # EXTRA_CFLAGS 10 | # EXTRA_LIBS 11 | # EXTRA_LIBDIRS 12 | # GCC_PREFIX = arch-toolchain- 13 | # OPT = [0-2] 14 | OPT ?= 0 15 | # FPIC = yes | no 16 | # RUN_PREFIX 17 | # RUN_ARGS 18 | # ARCH 19 | # ARCH_CFLAGS 20 | # ARCH_LFLAGS 21 | # COMPILER = g++ | gcc 22 | 23 | ############################################################################### 24 | # Checks 25 | ############################################################################### 26 | ifeq ($(MAKE_DIR),) 27 | $(error Missing MAKE_DIR) 28 | endif 29 | 30 | ############################################################################### 31 | # Arch options 32 | ############################################################################### 33 | ifneq ($(ARCH),) 34 | TARGET_IS_LIB=no 35 | include $(MAKE_DIR)/makefile.$(ARCH) 36 | endif 37 | 38 | ############################################################################### 39 | # Variables 40 | ############################################################################### 41 | ifneq ($(ARCH),) 42 | ARCH_TGT_DIR=$(ARCH) 43 | else 44 | ARCH_TGT_DIR=linux 45 | endif 46 | 47 | OBJ_DIR ?= obj.$(ARCH_TGT_DIR).$(TARGET)/ 48 | DEP_DIR ?= dep.$(ARCH_TGT_DIR).$(TARGET)/ 49 | EXE_DIR ?= build.$(ARCH_TGT_DIR).$(TARGET)/ 50 | 51 | ############################################################################### 52 | # Variables: GCC 53 | ############################################################################### 54 | QUIET ?= yes 55 | 56 | GCC_PREFIX ?= 57 | COMPILER ?= g++ 58 | 59 | ifeq ($(QUIET),yes) 60 | GCC = @$(GCC_PREFIX)$(COMPILER) 61 | OBJCOPY = @$(GCC_PREFIX)objcopy 62 | OBJDUMP = @$(GCC_PREFIX)objdump 63 | else 64 | GCC = $(GCC_PREFIX)$(COMPILER) 65 | OBJCOPY = $(GCC_PREFIX)objcopy 66 | OBJDUMP = $(GCC_PREFIX)objdump 67 | endif 68 | 69 | ############################################################################### 70 | # Variables: Compilation flags 71 | ############################################################################### 72 | 73 | # Additional include directories 74 | INCLUDE_PATH += $(SRC_DIR) 75 | 76 | # Flags 77 | CFLAGS = $(ARCH_CFLAGS) -O$(OPT) 78 | ifeq ($(FPIC), yes) 79 | CFLAGS += -fpic 80 | endif 81 | CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH)) 82 | CFLAGS += $(EXTRA_CFLAGS) 83 | 84 | LFLAGS = $(ARCH_LFLAGS) 85 | LFLAGS += $(patsubst %,-L%,$(EXTRA_LIBDIRS)) 86 | LFLAGS += $(EXTRA_LIBS) 87 | 88 | ############################################################################### 89 | # Variables: Lists of objects, source and deps 90 | ############################################################################### 91 | # SRC / Object list 92 | src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1))) 93 | src2dep = $(DEP_DIR)$(patsubst %,%.d,$(notdir $(1))) 94 | 95 | SRC := $(EXTRA_SRC) $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp)) $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.c)) 96 | OBJ ?= $(foreach src,$(SRC),$(call src2obj,$(src))) 97 | DEPS ?= $(foreach src,$(SRC),$(call src2dep,$(src))) 98 | 99 | ############################################################################### 100 | # Rules: Compilation macro 101 | ############################################################################### 102 | # Dependancy generation 103 | DEPFLAGS = -MT $$@ -MMD -MP -MF $(call src2dep,$(1)) 104 | 105 | define template_c 106 | $(call src2obj,$(1)): $(1) | $(OBJ_DIR) $(DEP_DIR) 107 | @echo "# Compiling $(notdir $(1))" 108 | $(GCC) $(CFLAGS) $(DEPFLAGS) -c $$< -o $$@ 109 | endef 110 | 111 | ############################################################################### 112 | # Rules 113 | ############################################################################### 114 | BUILD_TARGETS = $(EXE_DIR)$(TARGET) 115 | 116 | ENABLE_BIN ?= yes 117 | ENABLE_LST ?= yes 118 | 119 | ifeq ($(ENABLE_BIN),yes) 120 | BUILD_TARGETS += $(EXE_DIR)$(TARGET).bin 121 | endif 122 | ifeq ($(ENABLE_LST),yes) 123 | BUILD_TARGETS += $(EXE_DIR)$(TARGET).lst 124 | endif 125 | 126 | all: $(BUILD_TARGETS) 127 | 128 | $(OBJ_DIR) $(DEP_DIR) $(EXE_DIR): 129 | @mkdir -p $@ 130 | 131 | $(foreach src,$(SRC),$(eval $(call template_c,$(src)))) 132 | 133 | $(EXE_DIR)$(TARGET): $(OBJ) | $(EXE_DIR) 134 | @echo "# Building $(notdir $@)" 135 | $(GCC) -o $(EXE_DIR)$(TARGET) $(OBJ) $(LFLAGS) 136 | 137 | $(EXE_DIR)$(TARGET).bin: $(EXE_DIR)$(TARGET) 138 | @echo "# Building $(notdir $@)" 139 | $(OBJCOPY) -O binary $< $@ 140 | 141 | $(EXE_DIR)$(TARGET).lst: $(EXE_DIR)$(TARGET) 142 | @echo "# Building $(notdir $@)" 143 | $(OBJDUMP) -d $< > $@ 144 | 145 | clean: 146 | rm -rf $(EXE_DIR) $(OBJ_DIR) $(DEP_DIR) 147 | 148 | ############################################################################### 149 | # Rules: Dependancies 150 | ############################################################################### 151 | EXCLUDE_DEPS := clean 152 | ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(EXCLUDE_DEPS)))) 153 | -include $(DEPS) 154 | endif 155 | -------------------------------------------------------------------------------- /firmware/make/makefile.riscv: -------------------------------------------------------------------------------- 1 | ifeq ($(MAKE_DIR),) 2 | ${error - MAKE_DIR not specified} 3 | endif 4 | 5 | SW_ROOT := $(abspath $(MAKE_DIR)/..) 6 | 7 | ############################################################################### 8 | # RISC-V Flags 9 | ############################################################################### 10 | # GCC_PREFIX = arch-toolchain- 11 | GCC_PREFIX=riscv32-unknown-elf- 12 | # ARCH_CFLAGS 13 | ARCH_CFLAGS= 14 | # ARCH_LFLAGS 15 | ARCH_LFLAGS= 16 | # FPIC = yes | no 17 | FPIC = no 18 | # SHARED_LIB = yes | no 19 | SHARED_LIB = no 20 | # COMPILER = g++ | gcc 21 | COMPILER = gcc 22 | 23 | ifeq (,$(shell which $(GCC_PREFIX)gcc)) 24 | ${error - RISC-V GCC tools not available on PATH} 25 | endif 26 | 27 | ############################################################################### 28 | # Platform 29 | ############################################################################### 30 | PLATFORM ?= machine-fpga 31 | PLATFORM_DIR = $(SW_ROOT)/arch/riscv 32 | 33 | SRC_DIR += $(wildcard $(SW_ROOT)/drivers/*) 34 | 35 | BASE_ADDRESS ?= 0x80000000 36 | MEM_SIZE ?= 65535 37 | 38 | ARCH_CFLAGS += -DMACHINE_FPGA 39 | ARCH_LFLAGS += -nostartfiles -nodefaultlibs -lm 40 | 41 | ARCH_CFLAGS += -DCONFIG_USE_LOCAL_STRING_H 42 | ARCH_LFLAGS += -Wl,--defsym=BASE_ADDRESS=$(BASE_ADDRESS) 43 | ARCH_LFLAGS += -Wl,--defsym=MEM_SIZE=$(MEM_SIZE) 44 | 45 | EXTRA_SRC := $(PLATFORM_DIR)/boot.S $(EXTRA_SRC) 46 | 47 | LINKER_SCRIPT ?= linker_script.ld 48 | LINKER_SCRIPT_DIR ?= $(SW_ROOT)/arch/$(ARCH)/ 49 | EXTRA_CFLAGS += -DLINK_TYPE_RAM 50 | 51 | ARCH_LFLAGS += -T$(LINKER_SCRIPT_DIR)/$(LINKER_SCRIPT) 52 | SRC_DIR += $(PLATFORM_DIR) 53 | 54 | -------------------------------------------------------------------------------- /gateware/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/FPGAmp/4b9c9cf2c8b8be5f6efbc647dd42da29135d737b/gateware/README.md -------------------------------------------------------------------------------- /gateware/audio/audio_i2s.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Audio Controller 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2012-2019 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | module audio_i2s 36 | ( 37 | // Inputs 38 | input clk_i 39 | ,input rst_i 40 | ,input audio_clk_i 41 | ,input inport_tvalid_i 42 | ,input [ 31:0] inport_tdata_i 43 | ,input [ 3:0] inport_tstrb_i 44 | ,input [ 3:0] inport_tdest_i 45 | ,input inport_tlast_i 46 | 47 | // Outputs 48 | ,output inport_tready_o 49 | ,output i2s_sck_o 50 | ,output i2s_sdata_o 51 | ,output i2s_ws_o 52 | ); 53 | 54 | 55 | 56 | //----------------------------------------------------------------- 57 | // Registers 58 | //----------------------------------------------------------------- 59 | reg sck_q; 60 | reg sdata_q; 61 | reg ws_q; 62 | reg [4:0] bit_count_q; 63 | 64 | wire bit_clock_w = audio_clk_i; 65 | 66 | //----------------------------------------------------------------- 67 | // Buffer 68 | //----------------------------------------------------------------- 69 | reg [31:0] buffer_q; 70 | reg pop_q; 71 | 72 | always @ (posedge rst_i or posedge clk_i) 73 | if (rst_i) 74 | begin 75 | buffer_q <= 32'b0; 76 | pop_q <= 1'b0; 77 | end 78 | // Capture the next sample 1 SCK period before needed 79 | else if (bit_clock_w && (bit_count_q == 5'd0) && sck_q) 80 | begin 81 | buffer_q <= inport_tdata_i; 82 | pop_q <= 1'b1; 83 | end 84 | else 85 | pop_q <= 1'b0; 86 | 87 | assign inport_tready_o = pop_q; 88 | 89 | //----------------------------------------------------------------- 90 | // I2S Output Generator 91 | //----------------------------------------------------------------- 92 | reg next_data_q; 93 | 94 | always @ (posedge rst_i or posedge clk_i) 95 | if (rst_i) 96 | begin 97 | bit_count_q <= 5'd31; 98 | sdata_q <= 1'b0; 99 | ws_q <= 1'b0; 100 | sck_q <= 1'b0; 101 | next_data_q <= 1'b0; 102 | end 103 | else if (bit_clock_w) 104 | begin 105 | // SCK 1->0 - Falling Edge - drive SDATA 106 | if (sck_q) 107 | begin 108 | // SDATA lags WS by 1 cycle 109 | sdata_q <= next_data_q; 110 | 111 | // Drive data MSB first 112 | next_data_q <= buffer_q[bit_count_q]; 113 | 114 | // WS = 0 (left), 1 = (right) 115 | ws_q <= ~bit_count_q[4]; 116 | 117 | bit_count_q <= bit_count_q - 5'd1; 118 | end 119 | 120 | sck_q <= ~sck_q; 121 | end 122 | 123 | assign i2s_sck_o = sck_q; 124 | assign i2s_sdata_o = sdata_q; 125 | assign i2s_ws_o = ws_q; 126 | 127 | 128 | endmodule 129 | -------------------------------------------------------------------------------- /gateware/audio/audio_spdif.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Audio Controller 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2012-2019 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | module audio_spdif 36 | ( 37 | // Inputs 38 | input clk_i 39 | ,input rst_i 40 | ,input audio_clk_i 41 | ,input inport_tvalid_i 42 | ,input [ 31:0] inport_tdata_i 43 | ,input [ 3:0] inport_tstrb_i 44 | ,input [ 3:0] inport_tdest_i 45 | ,input inport_tlast_i 46 | 47 | // Outputs 48 | ,output inport_tready_o 49 | ,output spdif_o 50 | ); 51 | 52 | 53 | 54 | 55 | wire bit_clock_w = audio_clk_i; 56 | 57 | //----------------------------------------------------------------- 58 | // Core SPDIF 59 | //----------------------------------------------------------------- 60 | spdif_core 61 | u_core 62 | ( 63 | .clk_i(clk_i), 64 | .rst_i(rst_i), 65 | 66 | .bit_out_en_i(bit_clock_w), 67 | 68 | .spdif_o(spdif_o), 69 | 70 | .sample_i(inport_tdata_i), 71 | .sample_req_o(inport_tready_o) 72 | ); 73 | 74 | 75 | endmodule 76 | -------------------------------------------------------------------------------- /gateware/cpu/dcache_core_data_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | module dcache_core_data_ram 42 | ( 43 | // Inputs 44 | input clk0_i 45 | ,input rst0_i 46 | ,input [ 10:0] addr0_i 47 | ,input [ 31:0] data0_i 48 | ,input [ 3:0] wr0_i 49 | ,input clk1_i 50 | ,input rst1_i 51 | ,input [ 10:0] addr1_i 52 | ,input [ 31:0] data1_i 53 | ,input [ 3:0] wr1_i 54 | 55 | // Outputs 56 | ,output [ 31:0] data0_o 57 | ,output [ 31:0] data1_o 58 | ); 59 | 60 | 61 | 62 | //----------------------------------------------------------------- 63 | // Dual Port RAM 8KB 64 | // Mode: Read First 65 | //----------------------------------------------------------------- 66 | /* verilator lint_off MULTIDRIVEN */ 67 | reg [31:0] ram [2047:0] /*verilator public*/; 68 | /* verilator lint_on MULTIDRIVEN */ 69 | 70 | reg [31:0] ram_read0_q; 71 | reg [31:0] ram_read1_q; 72 | 73 | 74 | // Synchronous write 75 | always @ (posedge clk0_i) 76 | begin 77 | if (wr0_i[0]) 78 | ram[addr0_i][7:0] <= data0_i[7:0]; 79 | if (wr0_i[1]) 80 | ram[addr0_i][15:8] <= data0_i[15:8]; 81 | if (wr0_i[2]) 82 | ram[addr0_i][23:16] <= data0_i[23:16]; 83 | if (wr0_i[3]) 84 | ram[addr0_i][31:24] <= data0_i[31:24]; 85 | 86 | ram_read0_q <= ram[addr0_i]; 87 | end 88 | 89 | always @ (posedge clk1_i) 90 | begin 91 | if (wr1_i[0]) 92 | ram[addr1_i][7:0] <= data1_i[7:0]; 93 | if (wr1_i[1]) 94 | ram[addr1_i][15:8] <= data1_i[15:8]; 95 | if (wr1_i[2]) 96 | ram[addr1_i][23:16] <= data1_i[23:16]; 97 | if (wr1_i[3]) 98 | ram[addr1_i][31:24] <= data1_i[31:24]; 99 | 100 | ram_read1_q <= ram[addr1_i]; 101 | end 102 | 103 | 104 | assign data0_o = ram_read0_q; 105 | assign data1_o = ram_read1_q; 106 | 107 | 108 | 109 | endmodule 110 | -------------------------------------------------------------------------------- /gateware/cpu/dcache_core_tag_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | module dcache_core_tag_ram 42 | ( 43 | // Inputs 44 | input clk0_i 45 | ,input rst0_i 46 | ,input [ 7:0] addr0_i 47 | ,input clk1_i 48 | ,input rst1_i 49 | ,input [ 7:0] addr1_i 50 | ,input [ 20:0] data1_i 51 | ,input wr1_i 52 | 53 | // Outputs 54 | ,output [ 20:0] data0_o 55 | ); 56 | 57 | 58 | 59 | //----------------------------------------------------------------- 60 | // Tag RAM 0KB (256 x 21) 61 | // Mode: Write First 62 | //----------------------------------------------------------------- 63 | /* verilator lint_off MULTIDRIVEN */ 64 | reg [20:0] ram [255:0] /*verilator public*/; 65 | /* verilator lint_on MULTIDRIVEN */ 66 | 67 | reg [20:0] ram_read0_q; 68 | 69 | always @ (posedge clk1_i) 70 | begin 71 | if (wr1_i) 72 | ram[addr1_i] <= data1_i; 73 | 74 | ram_read0_q <= ram[addr0_i]; 75 | end 76 | 77 | 78 | reg data0_wr_q; 79 | always @ (posedge clk1_i ) 80 | if (rst1_i) 81 | data0_wr_q <= 1'b0; 82 | else 83 | data0_wr_q <= (|wr1_i) && (addr1_i == addr0_i); 84 | 85 | reg [20:0] data0_bypass_q; 86 | always @ (posedge clk1_i) 87 | data0_bypass_q <= data1_i; 88 | 89 | assign data0_o = data0_wr_q ? data0_bypass_q : ram_read0_q; 90 | 91 | 92 | 93 | endmodule 94 | -------------------------------------------------------------------------------- /gateware/cpu/icache_data_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | module icache_data_ram 42 | ( 43 | // Inputs 44 | input clk_i 45 | ,input rst_i 46 | ,input [ 10:0] addr_i 47 | ,input [ 31:0] data_i 48 | ,input wr_i 49 | 50 | // Outputs 51 | ,output [ 31:0] data_o 52 | ); 53 | 54 | 55 | 56 | 57 | //----------------------------------------------------------------- 58 | // Single Port RAM 8KB 59 | // Mode: Read First 60 | //----------------------------------------------------------------- 61 | reg [31:0] ram [2047:0] /*verilator public*/; 62 | reg [31:0] ram_read_q; 63 | 64 | 65 | // Synchronous write 66 | always @ (posedge clk_i) 67 | begin 68 | if (wr_i) 69 | ram[addr_i] <= data_i; 70 | ram_read_q <= ram[addr_i]; 71 | end 72 | 73 | assign data_o = ram_read_q; 74 | 75 | 76 | endmodule 77 | -------------------------------------------------------------------------------- /gateware/cpu/icache_tag_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | module icache_tag_ram 42 | ( 43 | // Inputs 44 | input clk_i 45 | ,input rst_i 46 | ,input [ 7:0] addr_i 47 | ,input [ 19:0] data_i 48 | ,input wr_i 49 | 50 | // Outputs 51 | ,output [ 19:0] data_o 52 | ); 53 | 54 | 55 | 56 | 57 | //----------------------------------------------------------------- 58 | // Single Port RAM 0KB 59 | // Mode: Read First 60 | //----------------------------------------------------------------- 61 | reg [19:0] ram [255:0] /*verilator public*/; 62 | reg [19:0] ram_read_q; 63 | 64 | 65 | // Synchronous write 66 | always @ (posedge clk_i) 67 | begin 68 | if (wr_i) 69 | ram[addr_i] <= data_i; 70 | ram_read_q <= ram[addr_i]; 71 | end 72 | 73 | assign data_o = ram_read_q; 74 | 75 | 76 | endmodule 77 | -------------------------------------------------------------------------------- /gateware/dbg_bridge/dbg_bridge_fifo.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // UART -> AXI Debug Bridge 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2017-2019 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: LGPL 10 | //----------------------------------------------------------------- 11 | // 12 | // This source file may be used and distributed without 13 | // restriction provided that this copyright statement is not 14 | // removed from the file and that any derivative work contains 15 | // the original copyright notice and the associated disclaimer. 16 | // 17 | // This source file is free software; you can redistribute it 18 | // and/or modify it under the terms of the GNU Lesser General 19 | // Public License as published by the Free Software Foundation; 20 | // either version 2.1 of the License, or (at your option) any 21 | // later version. 22 | // 23 | // This source is distributed in the hope that it will be 24 | // useful, but WITHOUT ANY WARRANTY; without even the implied 25 | // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 26 | // PURPOSE. See the GNU Lesser General Public License for more 27 | // details. 28 | // 29 | // You should have received a copy of the GNU Lesser General 30 | // Public License along with this source; if not, write to the 31 | // Free Software Foundation, Inc., 59 Temple Place, Suite 330, 32 | // Boston, MA 02111-1307 USA 33 | //----------------------------------------------------------------- 34 | 35 | //----------------------------------------------------------------- 36 | // Generated File 37 | //----------------------------------------------------------------- 38 | module dbg_bridge_fifo 39 | //----------------------------------------------------------------- 40 | // Params 41 | //----------------------------------------------------------------- 42 | #( 43 | parameter WIDTH = 8, 44 | parameter DEPTH = 4, 45 | parameter ADDR_W = 2 46 | ) 47 | //----------------------------------------------------------------- 48 | // Ports 49 | //----------------------------------------------------------------- 50 | ( 51 | // Inputs 52 | input clk_i 53 | ,input rst_i 54 | ,input [WIDTH-1:0] data_in_i 55 | ,input push_i 56 | ,input pop_i 57 | 58 | // Outputs 59 | ,output [WIDTH-1:0] data_out_o 60 | ,output accept_o 61 | ,output valid_o 62 | ); 63 | 64 | //----------------------------------------------------------------- 65 | // Local Params 66 | //----------------------------------------------------------------- 67 | localparam COUNT_W = ADDR_W + 1; 68 | 69 | //----------------------------------------------------------------- 70 | // Registers 71 | //----------------------------------------------------------------- 72 | reg [WIDTH-1:0] ram_q[DEPTH-1:0]; 73 | reg [ADDR_W-1:0] rd_ptr_q; 74 | reg [ADDR_W-1:0] wr_ptr_q; 75 | reg [COUNT_W-1:0] count_q; 76 | 77 | //----------------------------------------------------------------- 78 | // Sequential 79 | //----------------------------------------------------------------- 80 | always @ (posedge clk_i ) 81 | if (rst_i) 82 | begin 83 | count_q <= {(COUNT_W) {1'b0}}; 84 | rd_ptr_q <= {(ADDR_W) {1'b0}}; 85 | wr_ptr_q <= {(ADDR_W) {1'b0}}; 86 | end 87 | else 88 | begin 89 | // Push 90 | if (push_i & accept_o) 91 | begin 92 | ram_q[wr_ptr_q] <= data_in_i; 93 | wr_ptr_q <= wr_ptr_q + 1; 94 | end 95 | 96 | // Pop 97 | if (pop_i & valid_o) 98 | rd_ptr_q <= rd_ptr_q + 1; 99 | 100 | // Count up 101 | if ((push_i & accept_o) & ~(pop_i & valid_o)) 102 | count_q <= count_q + 1; 103 | // Count down 104 | else if (~(push_i & accept_o) & (pop_i & valid_o)) 105 | count_q <= count_q - 1; 106 | end 107 | 108 | //------------------------------------------------------------------- 109 | // Combinatorial 110 | //------------------------------------------------------------------- 111 | /* verilator lint_off WIDTH */ 112 | assign valid_o = (count_q != 0); 113 | assign accept_o = (count_q != DEPTH); 114 | /* verilator lint_on WIDTH */ 115 | 116 | assign data_out_o = ram_q[rd_ptr_q]; 117 | 118 | endmodule 119 | -------------------------------------------------------------------------------- /gateware/dvi/dvi_framebuffer_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // DVI / HDMI Framebuffer 3 | // V0.1 4 | // github.com/ultraembedded 5 | // Copyright 2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: MIT 10 | //----------------------------------------------------------------- 11 | // Copyright (c) 2020 github.com/ultraembedded 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in all 21 | // copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | // SOFTWARE. 30 | //----------------------------------------------------------------- 31 | 32 | `define CONFIG 8'h0 33 | 34 | `define CONFIG_X2_MODE 2 35 | `define CONFIG_X2_MODE_DEFAULT 0 36 | `define CONFIG_X2_MODE_B 2 37 | `define CONFIG_X2_MODE_T 2 38 | `define CONFIG_X2_MODE_W 1 39 | `define CONFIG_X2_MODE_R 2:2 40 | 41 | `define CONFIG_INT_EN_SOF 1 42 | `define CONFIG_INT_EN_SOF_DEFAULT 0 43 | `define CONFIG_INT_EN_SOF_B 1 44 | `define CONFIG_INT_EN_SOF_T 1 45 | `define CONFIG_INT_EN_SOF_W 1 46 | `define CONFIG_INT_EN_SOF_R 1:1 47 | 48 | `define CONFIG_ENABLE 0 49 | `define CONFIG_ENABLE_DEFAULT 1 50 | `define CONFIG_ENABLE_B 0 51 | `define CONFIG_ENABLE_T 0 52 | `define CONFIG_ENABLE_W 1 53 | `define CONFIG_ENABLE_R 0:0 54 | 55 | `define STATUS 8'h4 56 | 57 | `define STATUS_FB_PENDING 31 58 | `define STATUS_FB_PENDING_DEFAULT 0 59 | `define STATUS_FB_PENDING_B 31 60 | `define STATUS_FB_PENDING_T 31 61 | `define STATUS_FB_PENDING_W 1 62 | `define STATUS_FB_PENDING_R 31:31 63 | 64 | `define STATUS_V_POS_DEFAULT 0 65 | `define STATUS_V_POS_B 16 66 | `define STATUS_V_POS_T 30 67 | `define STATUS_V_POS_W 15 68 | `define STATUS_V_POS_R 30:16 69 | 70 | `define STATUS_H_POS_DEFAULT 0 71 | `define STATUS_H_POS_B 0 72 | `define STATUS_H_POS_T 15 73 | `define STATUS_H_POS_W 16 74 | `define STATUS_H_POS_R 15:0 75 | 76 | `define FRAME_BUFFER 8'h8 77 | 78 | `define FRAME_BUFFER_ADDR_DEFAULT 196608 79 | `define FRAME_BUFFER_ADDR_B 8 80 | `define FRAME_BUFFER_ADDR_T 31 81 | `define FRAME_BUFFER_ADDR_W 24 82 | `define FRAME_BUFFER_ADDR_R 31:8 83 | 84 | -------------------------------------------------------------------------------- /gateware/dvi/dvi_resync.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // DVI / HDMI Framebuffer 3 | // V0.1 4 | // github.com/ultraembedded 5 | // Copyright 2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: MIT 10 | //----------------------------------------------------------------- 11 | // Copyright (c) 2020 github.com/ultraembedded 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in all 21 | // copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | // SOFTWARE. 30 | //----------------------------------------------------------------- 31 | module dvi_resync 32 | //----------------------------------------------------------------- 33 | // Params 34 | //----------------------------------------------------------------- 35 | #( 36 | parameter RESET_VAL = 1'b0 37 | ) 38 | //----------------------------------------------------------------- 39 | // Ports 40 | //----------------------------------------------------------------- 41 | ( 42 | input clk_i, 43 | input rst_i, 44 | input async_i, 45 | output sync_o 46 | ); 47 | 48 | (* ASYNC_REG = "TRUE" *) reg sync_ms; 49 | (* ASYNC_REG = "TRUE" *) reg sync_q; 50 | 51 | always @ (posedge clk_i or posedge rst_i) 52 | if (rst_i) 53 | begin 54 | sync_ms <= RESET_VAL; 55 | sync_q <= RESET_VAL; 56 | end 57 | else 58 | begin 59 | sync_ms <= async_i; 60 | sync_q <= sync_ms; 61 | end 62 | 63 | assign sync_o = sync_q; 64 | 65 | endmodule -------------------------------------------------------------------------------- /gateware/dvi/dvi_serialiser.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // DVI / HDMI Framebuffer 3 | // V0.1 4 | // github.com/ultraembedded 5 | // Copyright 2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: MIT 10 | //----------------------------------------------------------------- 11 | // Copyright (c) 2020 github.com/ultraembedded 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in all 21 | // copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | // SOFTWARE. 30 | //----------------------------------------------------------------- 31 | module dvi_serialiser 32 | ( 33 | input clk_i 34 | , input rst_i 35 | , input strobe_i 36 | , input [9:0] data_i 37 | , output serial_o 38 | ); 39 | 40 | `ifndef verilator 41 | ODDR 42 | #( 43 | .DDR_CLK_EDGE("SAME_EDGE") 44 | ,.INIT(1'b0) 45 | ,.SRTYPE("ASYNC") 46 | ) 47 | u_ddr_r 48 | ( 49 | .C(clk_i) 50 | ,.CE(1'b1) 51 | ,.D1(data_i[0]) 52 | ,.D2(data_i[1]) 53 | ,.Q(serial_o) 54 | ,.R(1'b0) 55 | ,.S(1'b0) 56 | ); 57 | `else 58 | // Hack - non-functional sim 59 | assign serial_o = clk_i ? data_i[0] : data_i[1]; 60 | `endif 61 | 62 | endmodule -------------------------------------------------------------------------------- /gateware/jpeg_decoder/jpeg_decoder_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // AXI-4 JPEG Decoder 3 | // V0.1 4 | // github.com/ultraembedded 5 | // Copyright 2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: MIT 10 | //----------------------------------------------------------------- 11 | // Copyright (c) 2020 github.com/ultraembedded 12 | // 13 | // Permission is hereby granted, free of charge, to any person obtaining a copy 14 | // of this software and associated documentation files (the "Software"), to deal 15 | // in the Software without restriction, including without limitation the rights 16 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | // copies of the Software, and to permit persons to whom the Software is 18 | // furnished to do so, subject to the following conditions: 19 | // 20 | // The above copyright notice and this permission notice shall be included in all 21 | // copies or substantial portions of the Software. 22 | // 23 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | // SOFTWARE. 30 | //----------------------------------------------------------------- 31 | 32 | `define JPEG_CTRL 8'h0 33 | 34 | `define JPEG_CTRL_START 31 35 | `define JPEG_CTRL_START_DEFAULT 0 36 | `define JPEG_CTRL_START_B 31 37 | `define JPEG_CTRL_START_T 31 38 | `define JPEG_CTRL_START_W 1 39 | `define JPEG_CTRL_START_R 31:31 40 | 41 | `define JPEG_CTRL_ABORT 30 42 | `define JPEG_CTRL_ABORT_DEFAULT 0 43 | `define JPEG_CTRL_ABORT_B 30 44 | `define JPEG_CTRL_ABORT_T 30 45 | `define JPEG_CTRL_ABORT_W 1 46 | `define JPEG_CTRL_ABORT_R 30:30 47 | 48 | `define JPEG_CTRL_LENGTH_DEFAULT 0 49 | `define JPEG_CTRL_LENGTH_B 0 50 | `define JPEG_CTRL_LENGTH_T 23 51 | `define JPEG_CTRL_LENGTH_W 24 52 | `define JPEG_CTRL_LENGTH_R 23:0 53 | 54 | `define JPEG_STATUS 8'h4 55 | 56 | `define JPEG_STATUS_BUSY 0 57 | `define JPEG_STATUS_BUSY_DEFAULT 0 58 | `define JPEG_STATUS_BUSY_B 0 59 | `define JPEG_STATUS_BUSY_T 0 60 | `define JPEG_STATUS_BUSY_W 1 61 | `define JPEG_STATUS_BUSY_R 0:0 62 | 63 | `define JPEG_SRC 8'h8 64 | 65 | `define JPEG_SRC_ADDR_DEFAULT 0 66 | `define JPEG_SRC_ADDR_B 0 67 | `define JPEG_SRC_ADDR_T 31 68 | `define JPEG_SRC_ADDR_W 32 69 | `define JPEG_SRC_ADDR_R 31:0 70 | 71 | `define JPEG_DST 8'hc 72 | 73 | `define JPEG_DST_ADDR_DEFAULT 0 74 | `define JPEG_DST_ADDR_B 0 75 | `define JPEG_DST_ADDR_T 31 76 | `define JPEG_DST_ADDR_W 32 77 | `define JPEG_DST_ADDR_R 31:0 78 | 79 | -------------------------------------------------------------------------------- /gateware/mmc/mmc_cmd_deserialiser.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // MMC (and derivative standards) Host 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | //----------------------------------------------------------------- 26 | // Module: Deserialiser 27 | //----------------------------------------------------------------- 28 | module mmc_cmd_deserialiser 29 | ( 30 | input clk_i 31 | ,input rst_i 32 | ,input bitclk_i 33 | ,input start_i 34 | ,input abort_i 35 | ,input r2_mode_i 36 | ,input data_i 37 | ,output [135:0] resp_o 38 | ,output active_o 39 | ,output complete_o 40 | ); 41 | 42 | reg clk_q; 43 | 44 | always @ (posedge clk_i ) 45 | if (rst_i) 46 | clk_q <= 1'b0; 47 | else 48 | clk_q <= bitclk_i; 49 | 50 | // Capture on rising edge 51 | wire capture_w = bitclk_i & ~clk_q; 52 | 53 | reg [7:0] index_q; 54 | 55 | localparam STATE_W = 3; 56 | 57 | // Current state 58 | localparam STATE_IDLE = 3'd0; 59 | localparam STATE_STARTED = 3'd1; 60 | localparam STATE_ACTIVE = 3'd2; 61 | localparam STATE_END = 3'd3; 62 | 63 | reg [STATE_W-1:0] state_q; 64 | reg [STATE_W-1:0] next_state_r; 65 | 66 | always @ * 67 | begin 68 | next_state_r = state_q; 69 | 70 | case (state_q) 71 | STATE_IDLE : 72 | begin 73 | if (start_i) 74 | next_state_r = STATE_STARTED; 75 | end 76 | STATE_STARTED: 77 | begin 78 | if (capture_w && !data_i) 79 | next_state_r = STATE_ACTIVE; 80 | end 81 | STATE_ACTIVE: 82 | begin 83 | if ((index_q == 8'd0) & capture_w) 84 | next_state_r = STATE_END; 85 | end 86 | STATE_END: 87 | begin 88 | next_state_r = STATE_IDLE; 89 | end 90 | default : 91 | ; 92 | endcase 93 | 94 | if (abort_i) 95 | next_state_r = STATE_IDLE; 96 | end 97 | 98 | always @ (posedge clk_i ) 99 | if (rst_i) 100 | state_q <= STATE_IDLE; 101 | else 102 | state_q <= next_state_r; 103 | 104 | 105 | always @ (posedge clk_i ) 106 | if (rst_i) 107 | index_q <= 8'd47; 108 | else if (start_i) 109 | index_q <= r2_mode_i ? 8'd135: 8'd46; 110 | else if (capture_w && state_q == STATE_ACTIVE) 111 | index_q <= index_q - 8'd1; 112 | 113 | reg [135:0] resp_q; 114 | 115 | always @ (posedge clk_i ) 116 | if (rst_i) 117 | resp_q <= 136'b0; 118 | else if (state_q == STATE_IDLE && start_i) 119 | resp_q <= 136'b0; 120 | else if (state_q == STATE_ACTIVE && capture_w) 121 | resp_q <= {resp_q[134:0], data_i}; 122 | 123 | assign active_o = (state_q != STATE_IDLE); 124 | assign complete_o = (state_q == STATE_END); 125 | assign resp_o = resp_q; 126 | 127 | endmodule -------------------------------------------------------------------------------- /gateware/mmc/mmc_cmd_serialiser.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // MMC (and derivative standards) Host 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | //----------------------------------------------------------------- 26 | // Module: Serialiser 27 | //----------------------------------------------------------------- 28 | module mmc_cmd_serialiser 29 | ( 30 | input clk_i 31 | ,input rst_i 32 | ,input bitclk_i 33 | ,input start_i 34 | ,input abort_i 35 | ,input [47:0] data_i 36 | ,output cmd_o 37 | ,output active_o 38 | ,output complete_o 39 | ); 40 | 41 | reg clk_q; 42 | 43 | always @ (posedge clk_i ) 44 | if (rst_i) 45 | clk_q <= 1'b0; 46 | else 47 | clk_q <= bitclk_i; 48 | 49 | // Drive on falling edge 50 | wire drive_w = ~bitclk_i & clk_q; 51 | 52 | reg [7:0] index_q; 53 | 54 | localparam STATE_W = 3; 55 | 56 | // Current state 57 | localparam STATE_IDLE = 3'd0; 58 | localparam STATE_STARTED = 3'd1; 59 | localparam STATE_ACTIVE = 3'd2; 60 | localparam STATE_END = 3'd3; 61 | 62 | reg [STATE_W-1:0] state_q; 63 | reg [STATE_W-1:0] next_state_r; 64 | 65 | always @ * 66 | begin 67 | next_state_r = state_q; 68 | 69 | case (state_q) 70 | STATE_IDLE : 71 | begin 72 | if (start_i) 73 | next_state_r = STATE_STARTED; 74 | end 75 | STATE_STARTED: 76 | begin 77 | if (drive_w) 78 | next_state_r = STATE_ACTIVE; 79 | end 80 | STATE_ACTIVE: 81 | begin 82 | if ((index_q == 8'd0) & drive_w) 83 | next_state_r = STATE_END; 84 | end 85 | STATE_END: 86 | begin 87 | if (drive_w) 88 | next_state_r = STATE_IDLE; 89 | end 90 | default : 91 | ; 92 | endcase 93 | 94 | if (abort_i) 95 | next_state_r = STATE_IDLE; 96 | end 97 | 98 | always @ (posedge clk_i ) 99 | if (rst_i) 100 | state_q <= STATE_IDLE; 101 | else 102 | state_q <= next_state_r; 103 | 104 | 105 | always @ (posedge clk_i ) 106 | if (rst_i) 107 | index_q <= 8'd47; 108 | else if (start_i) 109 | index_q <= 8'd47; 110 | else if (drive_w && state_q == STATE_ACTIVE) 111 | index_q <= index_q - 8'd1; 112 | 113 | wire [6:0] crc7_w; 114 | mmc_crc7 115 | u_crc7 116 | ( 117 | .clk_i(clk_i) 118 | ,.rst_i(rst_i) 119 | ,.clear_i(state_q == STATE_IDLE) 120 | ,.bitval_i(data_i[index_q[5:0]]) 121 | ,.enable_i(drive_w && (state_q == STATE_ACTIVE) && index_q > 8'd7) 122 | ,.crc_o(crc7_w) 123 | ); 124 | 125 | reg cmd_q; 126 | 127 | always @ (posedge clk_i ) 128 | if (rst_i) 129 | cmd_q <= 1'b1; 130 | else if (drive_w && state_q == STATE_ACTIVE) 131 | begin 132 | if (index_q > 8'd7) 133 | cmd_q <= data_i[index_q[5:0]]; 134 | else if (index_q == 8'd0) 135 | cmd_q <= 1'b1; 136 | else 137 | cmd_q <= crc7_w[index_q[5:0]-1]; 138 | end 139 | else if (complete_o) 140 | cmd_q <= 1'b1; 141 | 142 | assign cmd_o = cmd_q; 143 | assign active_o = (state_q != STATE_IDLE); 144 | assign complete_o = (state_q == STATE_END) & drive_w; 145 | 146 | endmodule 147 | -------------------------------------------------------------------------------- /gateware/mmc/mmc_crc16.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // MMC (and derivative standards) Host 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | //----------------------------------------------------------------- 26 | // Module: CRC16 27 | //----------------------------------------------------------------- 28 | module mmc_crc16 29 | ( 30 | input clk_i 31 | ,input rst_i 32 | ,input clear_i 33 | ,input bitval_i 34 | ,input enable_i 35 | ,output [15:0] crc_o 36 | ); 37 | 38 | reg [15:0] crc_q; 39 | 40 | always @ (posedge clk_i ) 41 | if (rst_i) 42 | crc_q <= 16'b0; 43 | else if (clear_i) 44 | crc_q <= 16'b0; 45 | else if (enable_i) 46 | begin 47 | crc_q[15] <= crc_q[14]; 48 | crc_q[14] <= crc_q[13]; 49 | crc_q[13] <= crc_q[12]; 50 | crc_q[12] <= crc_q[11] ^ (bitval_i ^ crc_q[15]); 51 | crc_q[11] <= crc_q[10]; 52 | crc_q[10] <= crc_q[9]; 53 | crc_q[9] <= crc_q[8]; 54 | crc_q[8] <= crc_q[7]; 55 | crc_q[7] <= crc_q[6]; 56 | crc_q[6] <= crc_q[5]; 57 | crc_q[5] <= crc_q[4] ^ (bitval_i ^ crc_q[15]); 58 | crc_q[4] <= crc_q[3]; 59 | crc_q[3] <= crc_q[2]; 60 | crc_q[2] <= crc_q[1]; 61 | crc_q[1] <= crc_q[0]; 62 | crc_q[0] <= bitval_i ^ crc_q[15]; 63 | end 64 | 65 | assign crc_o = crc_q; 66 | 67 | endmodule -------------------------------------------------------------------------------- /gateware/mmc/mmc_crc7.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // MMC (and derivative standards) Host 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | //----------------------------------------------------------------- 26 | // Module: CRC7 27 | //----------------------------------------------------------------- 28 | module mmc_crc7 29 | ( 30 | input clk_i 31 | ,input rst_i 32 | ,input clear_i 33 | ,input bitval_i 34 | ,input enable_i 35 | ,output [6:0] crc_o 36 | ); 37 | 38 | reg [6:0] crc_q; 39 | 40 | always @ (posedge clk_i ) 41 | if (rst_i) 42 | crc_q <= 7'b0; 43 | else if (clear_i) 44 | crc_q <= 7'b0; 45 | else if (enable_i) 46 | begin 47 | crc_q[6] <= crc_q[5]; 48 | crc_q[5] <= crc_q[4]; 49 | crc_q[4] <= crc_q[3]; 50 | crc_q[3] <= crc_q[2] ^ (bitval_i ^ crc_q[6]); 51 | crc_q[2] <= crc_q[1]; 52 | crc_q[1] <= crc_q[0]; 53 | crc_q[0] <= bitval_i ^ crc_q[6]; 54 | end 55 | 56 | assign crc_o = crc_q; 57 | 58 | endmodule 59 | -------------------------------------------------------------------------------- /gateware/mmc/mmc_dat_deserialiser.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // MMC (and derivative standards) Host 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | //----------------------------------------------------------------- 26 | // Module: Deserialiser 27 | //----------------------------------------------------------------- 28 | module mmc_dat_deserialiser 29 | ( 30 | input clk_i 31 | ,input rst_i 32 | ,input bitclk_i 33 | ,input start_i 34 | ,input abort_i 35 | ,input data_i 36 | ,input mode_4bit_i 37 | ,input [7:0] block_cnt_i 38 | ,output valid_o 39 | ,output [7:0] data_o 40 | ,output active_o 41 | ,output error_o 42 | ,output complete_o 43 | ); 44 | 45 | reg clk_q; 46 | 47 | always @ (posedge clk_i ) 48 | if (rst_i) 49 | clk_q <= 1'b0; 50 | else 51 | clk_q <= bitclk_i; 52 | 53 | // Capture on rising edge 54 | wire capture_w = bitclk_i & ~clk_q; 55 | 56 | reg [15:0] index_q; 57 | 58 | localparam STATE_W = 3; 59 | 60 | // Current state 61 | localparam STATE_IDLE = 3'd0; 62 | localparam STATE_STARTED = 3'd1; 63 | localparam STATE_ACTIVE = 3'd2; 64 | localparam STATE_END = 3'd3; 65 | 66 | reg [STATE_W-1:0] state_q; 67 | reg [STATE_W-1:0] next_state_r; 68 | reg [7:0] block_cnt_q; 69 | 70 | always @ * 71 | begin 72 | next_state_r = state_q; 73 | 74 | case (state_q) 75 | STATE_IDLE : 76 | begin 77 | if (start_i) 78 | next_state_r = STATE_STARTED; 79 | end 80 | STATE_STARTED: 81 | begin 82 | if (capture_w && !data_i) 83 | next_state_r = STATE_ACTIVE; 84 | end 85 | STATE_ACTIVE: 86 | begin 87 | if ((index_q == 16'd0) & capture_w) 88 | begin 89 | if (block_cnt_q != 8'd0) 90 | next_state_r = STATE_STARTED; 91 | else 92 | next_state_r = STATE_END; 93 | end 94 | end 95 | STATE_END: 96 | begin 97 | next_state_r = STATE_IDLE; 98 | end 99 | default : 100 | ; 101 | endcase 102 | 103 | if (abort_i) 104 | next_state_r = STATE_IDLE; 105 | end 106 | 107 | always @ (posedge clk_i ) 108 | if (rst_i) 109 | state_q <= STATE_IDLE; 110 | else 111 | state_q <= next_state_r; 112 | 113 | always @ (posedge clk_i ) 114 | if (rst_i) 115 | block_cnt_q <= 8'b0; 116 | else if ((state_q == STATE_IDLE) && start_i) 117 | block_cnt_q <= block_cnt_i; 118 | else if ((state_q == STATE_ACTIVE) && (index_q == 16'd0) && capture_w) 119 | block_cnt_q <= block_cnt_q - 8'd1; 120 | 121 | always @ (posedge clk_i ) 122 | if (rst_i) 123 | index_q <= 16'd0; 124 | else if (state_q == STATE_STARTED) 125 | index_q <= mode_4bit_i ? 16'd1040: 16'd4112; 126 | else if (capture_w && state_q == STATE_ACTIVE) 127 | index_q <= index_q - 16'd1; 128 | 129 | reg [7:0] data_q; 130 | 131 | always @ (posedge clk_i ) 132 | if (rst_i) 133 | data_q <= 8'b0; 134 | else if (state_q == STATE_STARTED) 135 | data_q <= 8'b0; 136 | else if (state_q == STATE_ACTIVE && capture_w) 137 | data_q <= {data_q[6:0], data_i}; 138 | 139 | reg [2:0] bitcnt_q; 140 | 141 | always @ (posedge clk_i ) 142 | if (rst_i) 143 | bitcnt_q <= 3'b0; 144 | else if (state_q == STATE_STARTED) 145 | bitcnt_q <= 3'b0; 146 | else if (state_q == STATE_ACTIVE && capture_w) 147 | bitcnt_q <= bitcnt_q + 3'd1; 148 | 149 | reg valid_q; 150 | 151 | always @ (posedge clk_i ) 152 | if (rst_i) 153 | valid_q <= 1'b0; 154 | else 155 | valid_q <= (state_q == STATE_ACTIVE && capture_w && bitcnt_q == 3'd7 && index_q > 16'd15); 156 | 157 | assign active_o = (state_q != STATE_IDLE); 158 | assign complete_o = (state_q == STATE_END); 159 | assign valid_o = valid_q; 160 | assign data_o = data_q; 161 | assign error_o = 1'b0; // TODO: Add CRC checking 162 | 163 | endmodule -------------------------------------------------------------------------------- /gateware/soc/gpio_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define GPIO_DIRECTION 8'h0 36 | 37 | `define GPIO_DIRECTION_OUTPUT_DEFAULT 0 38 | `define GPIO_DIRECTION_OUTPUT_B 0 39 | `define GPIO_DIRECTION_OUTPUT_T 31 40 | `define GPIO_DIRECTION_OUTPUT_W 32 41 | `define GPIO_DIRECTION_OUTPUT_R 31:0 42 | 43 | `define GPIO_INPUT 8'h4 44 | 45 | `define GPIO_INPUT_VALUE_DEFAULT 0 46 | `define GPIO_INPUT_VALUE_B 0 47 | `define GPIO_INPUT_VALUE_T 31 48 | `define GPIO_INPUT_VALUE_W 32 49 | `define GPIO_INPUT_VALUE_R 31:0 50 | 51 | `define GPIO_OUTPUT 8'h8 52 | 53 | `define GPIO_OUTPUT_DATA_DEFAULT 0 54 | `define GPIO_OUTPUT_DATA_B 0 55 | `define GPIO_OUTPUT_DATA_T 31 56 | `define GPIO_OUTPUT_DATA_W 32 57 | `define GPIO_OUTPUT_DATA_R 31:0 58 | 59 | `define GPIO_OUTPUT_SET 8'hc 60 | 61 | `define GPIO_OUTPUT_SET_DATA_DEFAULT 0 62 | `define GPIO_OUTPUT_SET_DATA_B 0 63 | `define GPIO_OUTPUT_SET_DATA_T 31 64 | `define GPIO_OUTPUT_SET_DATA_W 32 65 | `define GPIO_OUTPUT_SET_DATA_R 31:0 66 | 67 | `define GPIO_OUTPUT_CLR 8'h10 68 | 69 | `define GPIO_OUTPUT_CLR_DATA_DEFAULT 0 70 | `define GPIO_OUTPUT_CLR_DATA_B 0 71 | `define GPIO_OUTPUT_CLR_DATA_T 31 72 | `define GPIO_OUTPUT_CLR_DATA_W 32 73 | `define GPIO_OUTPUT_CLR_DATA_R 31:0 74 | 75 | `define GPIO_INT_MASK 8'h14 76 | 77 | `define GPIO_INT_MASK_ENABLE_DEFAULT 0 78 | `define GPIO_INT_MASK_ENABLE_B 0 79 | `define GPIO_INT_MASK_ENABLE_T 31 80 | `define GPIO_INT_MASK_ENABLE_W 32 81 | `define GPIO_INT_MASK_ENABLE_R 31:0 82 | 83 | `define GPIO_INT_SET 8'h18 84 | 85 | `define GPIO_INT_SET_SW_IRQ_DEFAULT 0 86 | `define GPIO_INT_SET_SW_IRQ_B 0 87 | `define GPIO_INT_SET_SW_IRQ_T 31 88 | `define GPIO_INT_SET_SW_IRQ_W 32 89 | `define GPIO_INT_SET_SW_IRQ_R 31:0 90 | 91 | `define GPIO_INT_CLR 8'h1c 92 | 93 | `define GPIO_INT_CLR_ACK_DEFAULT 0 94 | `define GPIO_INT_CLR_ACK_B 0 95 | `define GPIO_INT_CLR_ACK_T 31 96 | `define GPIO_INT_CLR_ACK_W 32 97 | `define GPIO_INT_CLR_ACK_R 31:0 98 | 99 | `define GPIO_INT_STATUS 8'h20 100 | 101 | `define GPIO_INT_STATUS_RAW_DEFAULT 0 102 | `define GPIO_INT_STATUS_RAW_B 0 103 | `define GPIO_INT_STATUS_RAW_T 31 104 | `define GPIO_INT_STATUS_RAW_W 32 105 | `define GPIO_INT_STATUS_RAW_R 31:0 106 | 107 | `define GPIO_INT_LEVEL 8'h24 108 | 109 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_DEFAULT 0 110 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_B 0 111 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_T 31 112 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_W 32 113 | `define GPIO_INT_LEVEL_ACTIVE_HIGH_R 31:0 114 | 115 | `define GPIO_INT_MODE 8'h28 116 | 117 | `define GPIO_INT_MODE_EDGE_DEFAULT 0 118 | `define GPIO_INT_MODE_EDGE_B 0 119 | `define GPIO_INT_MODE_EDGE_T 31 120 | `define GPIO_INT_MODE_EDGE_W 32 121 | `define GPIO_INT_MODE_EDGE_R 31:0 122 | 123 | -------------------------------------------------------------------------------- /gateware/soc/irq_ctrl_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define IRQ_ISR 8'h0 36 | 37 | `define IRQ_ISR_STATUS_DEFAULT 0 38 | `define IRQ_ISR_STATUS_B 0 39 | `define IRQ_ISR_STATUS_T 6 40 | `define IRQ_ISR_STATUS_W 7 41 | `define IRQ_ISR_STATUS_R 6:0 42 | 43 | `define IRQ_IPR 8'h4 44 | 45 | `define IRQ_IPR_PENDING_DEFAULT 0 46 | `define IRQ_IPR_PENDING_B 0 47 | `define IRQ_IPR_PENDING_T 6 48 | `define IRQ_IPR_PENDING_W 7 49 | `define IRQ_IPR_PENDING_R 6:0 50 | 51 | `define IRQ_IER 8'h8 52 | 53 | `define IRQ_IER_ENABLE_DEFAULT 0 54 | `define IRQ_IER_ENABLE_B 0 55 | `define IRQ_IER_ENABLE_T 6 56 | `define IRQ_IER_ENABLE_W 7 57 | `define IRQ_IER_ENABLE_R 6:0 58 | 59 | `define IRQ_IAR 8'hc 60 | 61 | `define IRQ_IAR_ACK_DEFAULT 0 62 | `define IRQ_IAR_ACK_B 0 63 | `define IRQ_IAR_ACK_T 6 64 | `define IRQ_IAR_ACK_W 7 65 | `define IRQ_IAR_ACK_R 6:0 66 | 67 | `define IRQ_SIE 8'h10 68 | 69 | `define IRQ_SIE_SET_DEFAULT 0 70 | `define IRQ_SIE_SET_B 0 71 | `define IRQ_SIE_SET_T 6 72 | `define IRQ_SIE_SET_W 7 73 | `define IRQ_SIE_SET_R 6:0 74 | 75 | `define IRQ_CIE 8'h14 76 | 77 | `define IRQ_CIE_CLR_DEFAULT 0 78 | `define IRQ_CIE_CLR_B 0 79 | `define IRQ_CIE_CLR_T 6 80 | `define IRQ_CIE_CLR_W 7 81 | `define IRQ_CIE_CLR_R 6:0 82 | 83 | `define IRQ_IVR 8'h18 84 | 85 | `define IRQ_IVR_VECTOR_DEFAULT 0 86 | `define IRQ_IVR_VECTOR_B 0 87 | `define IRQ_IVR_VECTOR_T 31 88 | `define IRQ_IVR_VECTOR_W 32 89 | `define IRQ_IVR_VECTOR_R 31:0 90 | 91 | `define IRQ_MER 8'h1c 92 | 93 | `define IRQ_MER_ME 0 94 | `define IRQ_MER_ME_DEFAULT 0 95 | `define IRQ_MER_ME_B 0 96 | `define IRQ_MER_ME_T 0 97 | `define IRQ_MER_ME_W 1 98 | `define IRQ_MER_ME_R 0:0 99 | 100 | -------------------------------------------------------------------------------- /gateware/soc/uart_lite_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // Basic Peripheral SoC 3 | // V1.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2020 6 | // 7 | // Email: admin@ultra-embedded.com 8 | // 9 | // License: GPL 10 | // If you would like a version with a more permissive license for 11 | // use in closed source commercial applications please contact me 12 | // for details. 13 | //----------------------------------------------------------------- 14 | // 15 | // This file is open source HDL; you can redistribute it and/or 16 | // modify it under the terms of the GNU General Public License as 17 | // published by the Free Software Foundation; either version 2 of 18 | // the License, or (at your option) any later version. 19 | // 20 | // This file is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU General Public License for more details. 24 | // 25 | // You should have received a copy of the GNU General Public 26 | // License along with this file; if not, write to the Free Software 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 28 | // USA 29 | //----------------------------------------------------------------- 30 | 31 | //----------------------------------------------------------------- 32 | // Generated File 33 | //----------------------------------------------------------------- 34 | 35 | `define ULITE_RX 8'h0 36 | 37 | `define ULITE_RX_DATA_DEFAULT 0 38 | `define ULITE_RX_DATA_B 0 39 | `define ULITE_RX_DATA_T 7 40 | `define ULITE_RX_DATA_W 8 41 | `define ULITE_RX_DATA_R 7:0 42 | 43 | `define ULITE_TX 8'h4 44 | 45 | `define ULITE_TX_DATA_DEFAULT 0 46 | `define ULITE_TX_DATA_B 0 47 | `define ULITE_TX_DATA_T 7 48 | `define ULITE_TX_DATA_W 8 49 | `define ULITE_TX_DATA_R 7:0 50 | 51 | `define ULITE_STATUS 8'h8 52 | 53 | `define ULITE_STATUS_IE 4 54 | `define ULITE_STATUS_IE_DEFAULT 0 55 | `define ULITE_STATUS_IE_B 4 56 | `define ULITE_STATUS_IE_T 4 57 | `define ULITE_STATUS_IE_W 1 58 | `define ULITE_STATUS_IE_R 4:4 59 | 60 | `define ULITE_STATUS_TXFULL 3 61 | `define ULITE_STATUS_TXFULL_DEFAULT 0 62 | `define ULITE_STATUS_TXFULL_B 3 63 | `define ULITE_STATUS_TXFULL_T 3 64 | `define ULITE_STATUS_TXFULL_W 1 65 | `define ULITE_STATUS_TXFULL_R 3:3 66 | 67 | `define ULITE_STATUS_TXEMPTY 2 68 | `define ULITE_STATUS_TXEMPTY_DEFAULT 0 69 | `define ULITE_STATUS_TXEMPTY_B 2 70 | `define ULITE_STATUS_TXEMPTY_T 2 71 | `define ULITE_STATUS_TXEMPTY_W 1 72 | `define ULITE_STATUS_TXEMPTY_R 2:2 73 | 74 | `define ULITE_STATUS_RXFULL 1 75 | `define ULITE_STATUS_RXFULL_DEFAULT 0 76 | `define ULITE_STATUS_RXFULL_B 1 77 | `define ULITE_STATUS_RXFULL_T 1 78 | `define ULITE_STATUS_RXFULL_W 1 79 | `define ULITE_STATUS_RXFULL_R 1:1 80 | 81 | `define ULITE_STATUS_RXVALID 0 82 | `define ULITE_STATUS_RXVALID_DEFAULT 0 83 | `define ULITE_STATUS_RXVALID_B 0 84 | `define ULITE_STATUS_RXVALID_T 0 85 | `define ULITE_STATUS_RXVALID_W 1 86 | `define ULITE_STATUS_RXVALID_R 0:0 87 | 88 | `define ULITE_CONTROL 8'hc 89 | 90 | `define ULITE_CONTROL_IE 4 91 | `define ULITE_CONTROL_IE_DEFAULT 0 92 | `define ULITE_CONTROL_IE_B 4 93 | `define ULITE_CONTROL_IE_T 4 94 | `define ULITE_CONTROL_IE_W 1 95 | `define ULITE_CONTROL_IE_R 4:4 96 | 97 | `define ULITE_CONTROL_RST_RX 1 98 | `define ULITE_CONTROL_RST_RX_DEFAULT 0 99 | `define ULITE_CONTROL_RST_RX_B 1 100 | `define ULITE_CONTROL_RST_RX_T 1 101 | `define ULITE_CONTROL_RST_RX_W 1 102 | `define ULITE_CONTROL_RST_RX_R 1:1 103 | 104 | `define ULITE_CONTROL_RST_TX 0 105 | `define ULITE_CONTROL_RST_TX_DEFAULT 0 106 | `define ULITE_CONTROL_RST_TX_B 0 107 | `define ULITE_CONTROL_RST_TX_T 0 108 | `define ULITE_CONTROL_RST_TX_W 1 109 | `define ULITE_CONTROL_RST_TX_R 0:0 110 | 111 | -------------------------------------------------------------------------------- /gateware/top_hdmi/artix7_pll.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | 26 | module artix7_pll 27 | ( 28 | // Inputs 29 | input clkref_i 30 | 31 | // Outputs 32 | ,output clkout0_o 33 | ,output clkout1_o 34 | ,output clkout2_o 35 | ,output clkout3_o 36 | ); 37 | 38 | 39 | 40 | 41 | 42 | wire clkref_buffered_w; 43 | wire clkfbout_w; 44 | wire clkfbout_buffered_w; 45 | wire pll_clkout0_w; 46 | wire pll_clkout0_buffered_w; 47 | wire pll_clkout1_w; 48 | wire pll_clkout1_buffered_w; 49 | wire pll_clkout2_w; 50 | wire pll_clkout2_buffered_w; 51 | wire pll_clkout3_w; 52 | wire pll_clkout3_buffered_w; 53 | 54 | // Input buffering 55 | IBUF IBUF_IN 56 | ( 57 | .I (clkref_i), 58 | .O (clkref_buffered_w) 59 | ); 60 | 61 | // Clocking primitive 62 | PLLE2_BASE 63 | #( 64 | .BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW 65 | .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360-360) 66 | .CLKIN1_PERIOD(10.0), // Input clock period in ns resolution 67 | .CLKFBOUT_MULT(10), // VCO=1000MHz 68 | 69 | // CLKOUTx_DIVIDE: Divide amount for each CLKOUT(1-128) 70 | .CLKOUT0_DIVIDE(10), // CLK0=100MHz 71 | .CLKOUT1_DIVIDE(5), // CLK1=200MHz 72 | .CLKOUT2_DIVIDE(20), // CLK2=50MHz 73 | .CLKOUT3_DIVIDE(4), // CLK3=250MHz 74 | 75 | // CLKOUTx_DUTY_CYCLE: Duty cycle for each CLKOUT 76 | .CLKOUT0_DUTY_CYCLE(0.5), 77 | .CLKOUT1_DUTY_CYCLE(0.5), 78 | .CLKOUT2_DUTY_CYCLE(0.5), 79 | .CLKOUT3_DUTY_CYCLE(0.5), 80 | 81 | // CLKOUTx_PHASE: Phase offset for each CLKOUT 82 | .CLKOUT0_PHASE(0.0), 83 | .CLKOUT1_PHASE(0.0), 84 | .CLKOUT2_PHASE(0.0), 85 | .CLKOUT3_PHASE(0.0), 86 | 87 | .DIVCLK_DIVIDE(1), // Master division value (1-56) 88 | .REF_JITTER1(0.0), // Ref. input jitter in UI (0.000-0.999) 89 | .STARTUP_WAIT("TRUE") // Delay DONE until PLL Locks ("TRUE"/"FALSE") 90 | ) 91 | u_pll 92 | ( 93 | .CLKFBOUT(clkfbout_w), 94 | .CLKOUT0(pll_clkout0_w), 95 | .CLKOUT1(pll_clkout1_w), 96 | .CLKOUT2(pll_clkout2_w), 97 | .CLKOUT3(pll_clkout3_w), 98 | .CLKOUT4(), 99 | .CLKOUT5(), 100 | .LOCKED(), 101 | .PWRDWN(1'b0), 102 | .RST(1'b0), 103 | .CLKIN1(clkref_buffered_w), 104 | .CLKFBIN(clkfbout_buffered_w) 105 | ); 106 | 107 | BUFH u_clkfb_buf 108 | ( 109 | .I(clkfbout_w), 110 | .O(clkfbout_buffered_w) 111 | ); 112 | 113 | //----------------------------------------------------------------- 114 | // CLK_OUT0 115 | //----------------------------------------------------------------- 116 | assign pll_clkout0_buffered_w = pll_clkout0_w; 117 | 118 | assign clkout0_o = pll_clkout0_buffered_w; 119 | 120 | 121 | //----------------------------------------------------------------- 122 | // CLK_OUT1 123 | //----------------------------------------------------------------- 124 | assign pll_clkout1_buffered_w = pll_clkout1_w; 125 | 126 | assign clkout1_o = pll_clkout1_buffered_w; 127 | 128 | 129 | //----------------------------------------------------------------- 130 | // CLK_OUT2 131 | //----------------------------------------------------------------- 132 | assign pll_clkout2_buffered_w = pll_clkout2_w; 133 | 134 | assign clkout2_o = pll_clkout2_buffered_w; 135 | 136 | 137 | //----------------------------------------------------------------- 138 | // CLK_OUT3 139 | //----------------------------------------------------------------- 140 | assign pll_clkout3_buffered_w = pll_clkout3_w; 141 | 142 | assign clkout3_o = pll_clkout3_buffered_w; 143 | 144 | 145 | endmodule 146 | -------------------------------------------------------------------------------- /gateware/top_hdmi/mclk_gen.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | module mclk_gen 26 | ( 27 | input clk_i 28 | ,input rst_i 29 | ,output mclk_o 30 | ); 31 | 32 | // 2.214427438 = (*2 = 4.42885 -> 50÷11.2896) 33 | wire [15:0] audio_clk_div_whole_cycles_out_w = 16'd2; 34 | wire [15:0] audio_clk_frac_numerator_out_w = 16'd2144; 35 | wire [15:0] audio_clk_frac_denominator_out_w = 16'd10000; 36 | 37 | //----------------------------------------------------------------- 38 | // Clock Generator 39 | //----------------------------------------------------------------- 40 | reg clk_out_q; 41 | reg clk_en_q; 42 | reg [15:0] clk_div_q; 43 | reg [15:0] clk_div_r; 44 | reg [31:0] fraction_q; 45 | reg [31:0] fraction_r; 46 | 47 | /* verilator lint_off WIDTH */ 48 | always @ * 49 | begin 50 | clk_div_r = clk_div_q; 51 | fraction_r = fraction_q; 52 | 53 | case (clk_div_q) 54 | 0 : 55 | begin 56 | clk_div_r = clk_div_q + 16'd1; 57 | end 58 | audio_clk_div_whole_cycles_out_w - 16'd1: 59 | begin 60 | if (fraction_q < (audio_clk_frac_denominator_out_w - audio_clk_frac_numerator_out_w)) 61 | begin 62 | fraction_r = fraction_q + audio_clk_frac_numerator_out_w; 63 | clk_div_r = 16'd0; 64 | end 65 | else 66 | begin 67 | fraction_r = fraction_q + audio_clk_frac_numerator_out_w - audio_clk_frac_denominator_out_w; 68 | clk_div_r = clk_div_q + 16'd1; 69 | end 70 | end 71 | audio_clk_div_whole_cycles_out_w: 72 | begin 73 | clk_div_r = 16'd0; 74 | end 75 | 76 | default: 77 | begin 78 | clk_div_r = clk_div_q + 16'd1; 79 | end 80 | endcase 81 | end 82 | /* verilator lint_on WIDTH */ 83 | 84 | always @ (posedge clk_i ) 85 | if (rst_i) 86 | clk_div_q <= 16'd0; 87 | else 88 | clk_div_q <= clk_div_r; 89 | 90 | always @ (posedge clk_i ) 91 | if (rst_i) 92 | fraction_q <= 32'd0; 93 | else 94 | fraction_q <= fraction_r; 95 | 96 | always @ (posedge clk_i ) 97 | if (rst_i) 98 | clk_en_q <= 1'b0; 99 | else 100 | clk_en_q <= (clk_div_q == 16'd0); 101 | 102 | always @ (posedge clk_i ) 103 | if (rst_i) 104 | clk_out_q <= 1'b1; 105 | else if (clk_en_q) 106 | clk_out_q <= ~clk_out_q; 107 | 108 | assign mclk_o = clk_out_q; 109 | 110 | endmodule 111 | -------------------------------------------------------------------------------- /gateware/top_hdmi/reset_gen.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | module reset_gen 26 | ( 27 | input clk_i, 28 | output rst_o 29 | ); 30 | 31 | reg [3:0] count_q = 4'b0; 32 | reg rst_q = 1'b1; 33 | 34 | always @(posedge clk_i) 35 | if (count_q != 4'hF) 36 | count_q <= count_q + 4'd1; 37 | else 38 | rst_q <= 1'b0; 39 | 40 | assign rst_o = rst_q; 41 | 42 | endmodule -------------------------------------------------------------------------------- /gateware/top_hdmi_720p/artix7_pll.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | 26 | module artix7_pll 27 | ( 28 | // Inputs 29 | input clkref_i 30 | 31 | // Outputs 32 | ,output clkout0_o 33 | ,output clkout1_o 34 | ,output clkout2_o 35 | ,output clkout3_o 36 | ); 37 | 38 | 39 | 40 | 41 | 42 | wire clkref_buffered_w; 43 | wire clkfbout_w; 44 | wire clkfbout_buffered_w; 45 | wire pll_clkout0_w; 46 | wire pll_clkout0_buffered_w; 47 | wire pll_clkout1_w; 48 | wire pll_clkout1_buffered_w; 49 | wire pll_clkout2_w; 50 | wire pll_clkout2_buffered_w; 51 | wire pll_clkout3_w; 52 | wire pll_clkout3_buffered_w; 53 | 54 | // Input buffering 55 | IBUF IBUF_IN 56 | ( 57 | .I (clkref_i), 58 | .O (clkref_buffered_w) 59 | ); 60 | 61 | // Clocking primitive 62 | PLLE2_BASE 63 | #( 64 | .BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW 65 | .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360-360) 66 | .CLKIN1_PERIOD(10.0), // Input clock period in ns resolution 67 | .CLKFBOUT_MULT(12), // VCO=1200MHz 68 | 69 | // CLKOUTx_DIVIDE: Divide amount for each CLKOUT(1-128) 70 | .CLKOUT0_DIVIDE(12), // CLK0=100MHz 71 | .CLKOUT1_DIVIDE(6), // CLK1=200MHz 72 | .CLKOUT2_DIVIDE(20), // CLK2=60MHz 73 | .CLKOUT3_DIVIDE(4), // CLK3=300MHz 74 | 75 | // CLKOUTx_DUTY_CYCLE: Duty cycle for each CLKOUT 76 | .CLKOUT0_DUTY_CYCLE(0.5), 77 | .CLKOUT1_DUTY_CYCLE(0.5), 78 | .CLKOUT2_DUTY_CYCLE(0.5), 79 | .CLKOUT3_DUTY_CYCLE(0.5), 80 | 81 | // CLKOUTx_PHASE: Phase offset for each CLKOUT 82 | .CLKOUT0_PHASE(0.0), 83 | .CLKOUT1_PHASE(0.0), 84 | .CLKOUT2_PHASE(0.0), 85 | .CLKOUT3_PHASE(0.0), 86 | 87 | .DIVCLK_DIVIDE(1), // Master division value (1-56) 88 | .REF_JITTER1(0.0), // Ref. input jitter in UI (0.000-0.999) 89 | .STARTUP_WAIT("TRUE") // Delay DONE until PLL Locks ("TRUE"/"FALSE") 90 | ) 91 | u_pll 92 | ( 93 | .CLKFBOUT(clkfbout_w), 94 | .CLKOUT0(pll_clkout0_w), 95 | .CLKOUT1(pll_clkout1_w), 96 | .CLKOUT2(pll_clkout2_w), 97 | .CLKOUT3(pll_clkout3_w), 98 | .CLKOUT4(), 99 | .CLKOUT5(), 100 | .LOCKED(), 101 | .PWRDWN(1'b0), 102 | .RST(1'b0), 103 | .CLKIN1(clkref_buffered_w), 104 | .CLKFBIN(clkfbout_buffered_w) 105 | ); 106 | 107 | BUFH u_clkfb_buf 108 | ( 109 | .I(clkfbout_w), 110 | .O(clkfbout_buffered_w) 111 | ); 112 | 113 | //----------------------------------------------------------------- 114 | // CLK_OUT0 115 | //----------------------------------------------------------------- 116 | assign pll_clkout0_buffered_w = pll_clkout0_w; 117 | 118 | assign clkout0_o = pll_clkout0_buffered_w; 119 | 120 | 121 | //----------------------------------------------------------------- 122 | // CLK_OUT1 123 | //----------------------------------------------------------------- 124 | assign pll_clkout1_buffered_w = pll_clkout1_w; 125 | 126 | assign clkout1_o = pll_clkout1_buffered_w; 127 | 128 | 129 | //----------------------------------------------------------------- 130 | // CLK_OUT2 131 | //----------------------------------------------------------------- 132 | assign pll_clkout2_buffered_w = pll_clkout2_w; 133 | 134 | assign clkout2_o = pll_clkout2_buffered_w; 135 | 136 | 137 | //----------------------------------------------------------------- 138 | // CLK_OUT3 139 | //----------------------------------------------------------------- 140 | assign pll_clkout3_buffered_w = pll_clkout3_w; 141 | 142 | assign clkout3_o = pll_clkout3_buffered_w; 143 | 144 | 145 | endmodule 146 | -------------------------------------------------------------------------------- /gateware/top_hdmi_720p/mclk_gen.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | module mclk_gen 26 | ( 27 | input clk_i 28 | ,input rst_i 29 | ,output mclk_o 30 | ); 31 | 32 | // 2.657312925170068 = (*2 = 4.42885 -> 60÷11.2896) 33 | wire [15:0] audio_clk_div_whole_cycles_out_w = 16'd2; 34 | wire [15:0] audio_clk_frac_numerator_out_w = 16'd6573; 35 | wire [15:0] audio_clk_frac_denominator_out_w = 16'd10000; 36 | 37 | //----------------------------------------------------------------- 38 | // Clock Generator 39 | //----------------------------------------------------------------- 40 | reg clk_out_q; 41 | reg clk_en_q; 42 | reg [15:0] clk_div_q; 43 | reg [15:0] clk_div_r; 44 | reg [31:0] fraction_q; 45 | reg [31:0] fraction_r; 46 | 47 | /* verilator lint_off WIDTH */ 48 | always @ * 49 | begin 50 | clk_div_r = clk_div_q; 51 | fraction_r = fraction_q; 52 | 53 | case (clk_div_q) 54 | 0 : 55 | begin 56 | clk_div_r = clk_div_q + 16'd1; 57 | end 58 | audio_clk_div_whole_cycles_out_w - 16'd1: 59 | begin 60 | if (fraction_q < (audio_clk_frac_denominator_out_w - audio_clk_frac_numerator_out_w)) 61 | begin 62 | fraction_r = fraction_q + audio_clk_frac_numerator_out_w; 63 | clk_div_r = 16'd0; 64 | end 65 | else 66 | begin 67 | fraction_r = fraction_q + audio_clk_frac_numerator_out_w - audio_clk_frac_denominator_out_w; 68 | clk_div_r = clk_div_q + 16'd1; 69 | end 70 | end 71 | audio_clk_div_whole_cycles_out_w: 72 | begin 73 | clk_div_r = 16'd0; 74 | end 75 | 76 | default: 77 | begin 78 | clk_div_r = clk_div_q + 16'd1; 79 | end 80 | endcase 81 | end 82 | /* verilator lint_on WIDTH */ 83 | 84 | always @ (posedge clk_i ) 85 | if (rst_i) 86 | clk_div_q <= 16'd0; 87 | else 88 | clk_div_q <= clk_div_r; 89 | 90 | always @ (posedge clk_i ) 91 | if (rst_i) 92 | fraction_q <= 32'd0; 93 | else 94 | fraction_q <= fraction_r; 95 | 96 | always @ (posedge clk_i ) 97 | if (rst_i) 98 | clk_en_q <= 1'b0; 99 | else 100 | clk_en_q <= (clk_div_q == 16'd0); 101 | 102 | always @ (posedge clk_i ) 103 | if (rst_i) 104 | clk_out_q <= 1'b1; 105 | else if (clk_en_q) 106 | clk_out_q <= ~clk_out_q; 107 | 108 | assign mclk_o = clk_out_q; 109 | 110 | endmodule 111 | -------------------------------------------------------------------------------- /gateware/top_hdmi_720p/reset_gen.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | module reset_gen 26 | ( 27 | input clk_i, 28 | output rst_o 29 | ); 30 | 31 | reg [3:0] count_q = 4'b0; 32 | reg rst_q = 1'b1; 33 | 34 | always @(posedge clk_i) 35 | if (count_q != 4'hF) 36 | count_q <= count_q + 4'd1; 37 | else 38 | rst_q <= 1'b0; 39 | 40 | assign rst_o = rst_q; 41 | 42 | endmodule -------------------------------------------------------------------------------- /gateware/top_vga/artix7_pll.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | 26 | module artix7_pll 27 | ( 28 | // Inputs 29 | input clkref_i 30 | 31 | // Outputs 32 | ,output clkout0_o 33 | ,output clkout1_o 34 | ,output clkout2_o 35 | ,output clkout3_o 36 | ); 37 | 38 | 39 | 40 | 41 | 42 | wire clkref_buffered_w; 43 | wire clkfbout_w; 44 | wire clkfbout_buffered_w; 45 | wire pll_clkout0_w; 46 | wire pll_clkout0_buffered_w; 47 | wire pll_clkout1_w; 48 | wire pll_clkout1_buffered_w; 49 | wire pll_clkout2_w; 50 | wire pll_clkout2_buffered_w; 51 | wire pll_clkout3_w; 52 | wire pll_clkout3_buffered_w; 53 | 54 | // Input buffering 55 | IBUF IBUF_IN 56 | ( 57 | .I (clkref_i), 58 | .O (clkref_buffered_w) 59 | ); 60 | 61 | // Clocking primitive 62 | PLLE2_BASE 63 | #( 64 | .BANDWIDTH("OPTIMIZED"), // OPTIMIZED, HIGH, LOW 65 | .CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB, (-360-360) 66 | .CLKIN1_PERIOD(10.0), // Input clock period in ns resolution 67 | .CLKFBOUT_MULT(10), // VCO=1000MHz 68 | 69 | // CLKOUTx_DIVIDE: Divide amount for each CLKOUT(1-128) 70 | .CLKOUT0_DIVIDE(10), // CLK0=100MHz 71 | .CLKOUT1_DIVIDE(5), // CLK1=200MHz 72 | .CLKOUT2_DIVIDE(20), // CLK2=50MHz 73 | .CLKOUT3_DIVIDE(4), // CLK3=250MHz 74 | 75 | // CLKOUTx_DUTY_CYCLE: Duty cycle for each CLKOUT 76 | .CLKOUT0_DUTY_CYCLE(0.5), 77 | .CLKOUT1_DUTY_CYCLE(0.5), 78 | .CLKOUT2_DUTY_CYCLE(0.5), 79 | .CLKOUT3_DUTY_CYCLE(0.5), 80 | 81 | // CLKOUTx_PHASE: Phase offset for each CLKOUT 82 | .CLKOUT0_PHASE(0.0), 83 | .CLKOUT1_PHASE(0.0), 84 | .CLKOUT2_PHASE(0.0), 85 | .CLKOUT3_PHASE(0.0), 86 | 87 | .DIVCLK_DIVIDE(1), // Master division value (1-56) 88 | .REF_JITTER1(0.0), // Ref. input jitter in UI (0.000-0.999) 89 | .STARTUP_WAIT("TRUE") // Delay DONE until PLL Locks ("TRUE"/"FALSE") 90 | ) 91 | u_pll 92 | ( 93 | .CLKFBOUT(clkfbout_w), 94 | .CLKOUT0(pll_clkout0_w), 95 | .CLKOUT1(pll_clkout1_w), 96 | .CLKOUT2(pll_clkout2_w), 97 | .CLKOUT3(pll_clkout3_w), 98 | .CLKOUT4(), 99 | .CLKOUT5(), 100 | .LOCKED(), 101 | .PWRDWN(1'b0), 102 | .RST(1'b0), 103 | .CLKIN1(clkref_buffered_w), 104 | .CLKFBIN(clkfbout_buffered_w) 105 | ); 106 | 107 | BUFH u_clkfb_buf 108 | ( 109 | .I(clkfbout_w), 110 | .O(clkfbout_buffered_w) 111 | ); 112 | 113 | //----------------------------------------------------------------- 114 | // CLK_OUT0 115 | //----------------------------------------------------------------- 116 | assign pll_clkout0_buffered_w = pll_clkout0_w; 117 | 118 | assign clkout0_o = pll_clkout0_buffered_w; 119 | 120 | 121 | //----------------------------------------------------------------- 122 | // CLK_OUT1 123 | //----------------------------------------------------------------- 124 | assign pll_clkout1_buffered_w = pll_clkout1_w; 125 | 126 | assign clkout1_o = pll_clkout1_buffered_w; 127 | 128 | 129 | //----------------------------------------------------------------- 130 | // CLK_OUT2 131 | //----------------------------------------------------------------- 132 | assign pll_clkout2_buffered_w = pll_clkout2_w; 133 | 134 | assign clkout2_o = pll_clkout2_buffered_w; 135 | 136 | 137 | //----------------------------------------------------------------- 138 | // CLK_OUT3 139 | //----------------------------------------------------------------- 140 | assign pll_clkout3_buffered_w = pll_clkout3_w; 141 | 142 | assign clkout3_o = pll_clkout3_buffered_w; 143 | 144 | 145 | endmodule 146 | -------------------------------------------------------------------------------- /gateware/top_vga/mclk_gen.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | module mclk_gen 26 | ( 27 | input clk_i 28 | ,input rst_i 29 | ,output mclk_o 30 | ); 31 | 32 | // 2.214427438 = (*2 = 4.42885 -> 50÷11.2896) 33 | wire [15:0] audio_clk_div_whole_cycles_out_w = 16'd2; 34 | wire [15:0] audio_clk_frac_numerator_out_w = 16'd2144; 35 | wire [15:0] audio_clk_frac_denominator_out_w = 16'd10000; 36 | 37 | //----------------------------------------------------------------- 38 | // Clock Generator 39 | //----------------------------------------------------------------- 40 | reg clk_out_q; 41 | reg clk_en_q; 42 | reg [15:0] clk_div_q; 43 | reg [15:0] clk_div_r; 44 | reg [31:0] fraction_q; 45 | reg [31:0] fraction_r; 46 | 47 | /* verilator lint_off WIDTH */ 48 | always @ * 49 | begin 50 | clk_div_r = clk_div_q; 51 | fraction_r = fraction_q; 52 | 53 | case (clk_div_q) 54 | 0 : 55 | begin 56 | clk_div_r = clk_div_q + 16'd1; 57 | end 58 | audio_clk_div_whole_cycles_out_w - 16'd1: 59 | begin 60 | if (fraction_q < (audio_clk_frac_denominator_out_w - audio_clk_frac_numerator_out_w)) 61 | begin 62 | fraction_r = fraction_q + audio_clk_frac_numerator_out_w; 63 | clk_div_r = 16'd0; 64 | end 65 | else 66 | begin 67 | fraction_r = fraction_q + audio_clk_frac_numerator_out_w - audio_clk_frac_denominator_out_w; 68 | clk_div_r = clk_div_q + 16'd1; 69 | end 70 | end 71 | audio_clk_div_whole_cycles_out_w: 72 | begin 73 | clk_div_r = 16'd0; 74 | end 75 | 76 | default: 77 | begin 78 | clk_div_r = clk_div_q + 16'd1; 79 | end 80 | endcase 81 | end 82 | /* verilator lint_on WIDTH */ 83 | 84 | always @ (posedge clk_i ) 85 | if (rst_i) 86 | clk_div_q <= 16'd0; 87 | else 88 | clk_div_q <= clk_div_r; 89 | 90 | always @ (posedge clk_i ) 91 | if (rst_i) 92 | fraction_q <= 32'd0; 93 | else 94 | fraction_q <= fraction_r; 95 | 96 | always @ (posedge clk_i ) 97 | if (rst_i) 98 | clk_en_q <= 1'b0; 99 | else 100 | clk_en_q <= (clk_div_q == 16'd0); 101 | 102 | always @ (posedge clk_i ) 103 | if (rst_i) 104 | clk_out_q <= 1'b1; 105 | else if (clk_en_q) 106 | clk_out_q <= ~clk_out_q; 107 | 108 | assign mclk_o = clk_out_q; 109 | 110 | endmodule 111 | -------------------------------------------------------------------------------- /gateware/top_vga/reset_gen.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | module reset_gen 26 | ( 27 | input clk_i, 28 | output rst_o 29 | ); 30 | 31 | reg [3:0] count_q = 4'b0; 32 | reg rst_q = 1'b1; 33 | 34 | always @(posedge clk_i) 35 | if (count_q != 4'hF) 36 | count_q <= count_q + 4'd1; 37 | else 38 | rst_q <= 1'b0; 39 | 40 | assign rst_o = rst_q; 41 | 42 | endmodule -------------------------------------------------------------------------------- /gateware/vga/vga_framebuffer_defs.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // FPGA Media Player 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2020 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: Apache 2.0 10 | //----------------------------------------------------------------- 11 | // Copyright 2020 Ultra-Embedded.com 12 | // 13 | // Licensed under the Apache License, Version 2.0 (the "License"); 14 | // you may not use this file except in compliance with the License. 15 | // You may obtain a copy of the License at 16 | // 17 | // http://www.apache.org/licenses/LICENSE-2.0 18 | // 19 | // Unless required by applicable law or agreed to in writing, software 20 | // distributed under the License is distributed on an "AS IS" BASIS, 21 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 | // See the License for the specific language governing permissions and 23 | // limitations under the License. 24 | //----------------------------------------------------------------- 25 | 26 | `define CONFIG 8'h0 27 | 28 | `define CONFIG_X2_MODE 2 29 | `define CONFIG_X2_MODE_DEFAULT 0 30 | `define CONFIG_X2_MODE_B 2 31 | `define CONFIG_X2_MODE_T 2 32 | `define CONFIG_X2_MODE_W 1 33 | `define CONFIG_X2_MODE_R 2:2 34 | 35 | `define CONFIG_INT_EN_SOF 1 36 | `define CONFIG_INT_EN_SOF_DEFAULT 0 37 | `define CONFIG_INT_EN_SOF_B 1 38 | `define CONFIG_INT_EN_SOF_T 1 39 | `define CONFIG_INT_EN_SOF_W 1 40 | `define CONFIG_INT_EN_SOF_R 1:1 41 | 42 | `define CONFIG_ENABLE 0 43 | `define CONFIG_ENABLE_DEFAULT 1 44 | `define CONFIG_ENABLE_B 0 45 | `define CONFIG_ENABLE_T 0 46 | `define CONFIG_ENABLE_W 1 47 | `define CONFIG_ENABLE_R 0:0 48 | 49 | `define STATUS 8'h4 50 | 51 | `define STATUS_FB_PENDING 31 52 | `define STATUS_FB_PENDING_DEFAULT 0 53 | `define STATUS_FB_PENDING_B 31 54 | `define STATUS_FB_PENDING_T 31 55 | `define STATUS_FB_PENDING_W 1 56 | `define STATUS_FB_PENDING_R 31:31 57 | 58 | `define STATUS_V_POS_DEFAULT 0 59 | `define STATUS_V_POS_B 16 60 | `define STATUS_V_POS_T 30 61 | `define STATUS_V_POS_W 15 62 | `define STATUS_V_POS_R 30:16 63 | 64 | `define STATUS_H_POS_DEFAULT 0 65 | `define STATUS_H_POS_B 0 66 | `define STATUS_H_POS_T 15 67 | `define STATUS_H_POS_W 16 68 | `define STATUS_H_POS_R 15:0 69 | 70 | `define FRAME_BUFFER 8'h8 71 | 72 | `define FRAME_BUFFER_ADDR_DEFAULT 196608 73 | `define FRAME_BUFFER_ADDR_B 8 74 | `define FRAME_BUFFER_ADDR_T 31 75 | `define FRAME_BUFFER_ADDR_W 24 76 | `define FRAME_BUFFER_ADDR_R 31:8 77 | 78 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | ## Scripts 2 | 3 | Convert various video input file formats to a MJPEG container format supported by FPGAmp (requires ffmpeg and jpegtran) 4 | 5 | ``` 6 | # Convert input video file (input.avi) to required resolution and convert to MJPEG container 7 | ./convert.py -i input.avi -o output.mjpg 8 | 9 | # ... Copy output.mjpg to the SD/MMC card so that it is playable... 10 | ``` 11 | -------------------------------------------------------------------------------- /scripts/convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import argparse 4 | import os 5 | from subprocess import run, PIPE 6 | 7 | ################################################################## 8 | # Main 9 | ################################################################## 10 | def main(argv): 11 | 12 | input_files = [] 13 | 14 | parser = argparse.ArgumentParser() 15 | parser.add_argument('-i', dest='input', required=True, help='Input file') 16 | parser.add_argument('-o', dest='output', required=True, help='Output file') 17 | parser.add_argument('--width', dest='width', type=int, default=800, help='Video output width') 18 | parser.add_argument('--height', dest='height', type=int, default=600, help='Video output height') 19 | parser.add_argument('--fps', dest='fps', type=int, default=25, help='Video source FPS') 20 | args = vars(parser.parse_args()) 21 | 22 | input_file = args['input'] 23 | output_file = args['output'] 24 | 25 | # Calculate audio samples per frame 26 | frames_per_block = 128 27 | audio_samples_per_frame = 44100 / args['fps'] 28 | 29 | # Audio samples per frame not exact (this is meant to support 25 or 24 FPS) 30 | partial_audio = False 31 | if int(audio_samples_per_frame) != audio_samples_per_frame: 32 | partial_audio = True 33 | 34 | # 16-bit x 2 35 | audio_block_size = int(audio_samples_per_frame) * 4 36 | 37 | # Remove old temp files 38 | os.system("rm -rf output.video") 39 | os.system("rm -rf output.audio") 40 | os.system("rm -rf output.mp4") 41 | 42 | geometry = "%dx%d" % (args['width'], args['height']) 43 | print("# Convert to MP4 (scaled to %s)" % geometry) 44 | os.system("ffmpeg -i %s -vf scale=%s output.mp4" % (input_file, geometry)) 45 | 46 | print("# Convert video to JPEG stream") 47 | os.system("ffmpeg -i output.mp4 -qscale:v 2 -f singlejpeg pipe:1 > output.video") 48 | 49 | print("# Convert audio to PCM") 50 | os.system("ffmpeg -i output.mp4 -f s16le -acodec pcm_s16le -ar 44100 output.audio") 51 | 52 | video_file = 'output.video' 53 | audio_file = 'output.audio' 54 | 55 | print("# Transcoding to MJPEG") 56 | 57 | fout = open(output_file, 'wb') 58 | f_video = open(video_file, "rb") 59 | f_audio = open(audio_file, "rb") 60 | 61 | # Convert to supported file format 62 | data = f_video.read(1) 63 | last_b = None 64 | found_soi = False 65 | jpeg = bytearray() 66 | jpeg_group = [] 67 | frame_count= 0 68 | audio_idx = 0 69 | print ("Starting conversion") 70 | while data: 71 | jpeg.append(data[0]) 72 | 73 | # Detect SOI 74 | if not found_soi and data == b'\xd8' and last_b == b'\xff': 75 | found_soi = True 76 | # Detect EOI 77 | elif found_soi and data == b'\xd9' and last_b == b'\xff': 78 | found_soi = False 79 | 80 | # Transcode to baseline JPEG 81 | p = run(['jpegtran'], stdout=PIPE, input=bytes(jpeg)) 82 | jpeg = bytearray(p.stdout) 83 | 84 | # Read an audio blob to go with video frame 85 | if partial_audio and (audio_idx % 2) == 1: 86 | audio_blob = f_audio.read(audio_block_size+4) 87 | else: 88 | audio_blob = f_audio.read(audio_block_size) 89 | audio_idx += 1 90 | 91 | # Add video + audio frame tuple to list 92 | jpeg_group.append((jpeg,audio_blob)) 93 | 94 | # Reset JPEG handler 95 | jpeg = bytearray() 96 | 97 | # Progress print 98 | frame_count += 1 99 | if frame_count % 25 == 0: 100 | print ("\rFrame: %d" % frame_count, end='', flush=True) 101 | 102 | last_b = data 103 | 104 | # Read next JPEG stream byte 105 | data = f_video.read(1) 106 | 107 | # End of video stream or 128 video frames reached 108 | if len(jpeg_group) == frames_per_block or not data: 109 | # Build a directory of up-to 512 frames 110 | table = bytearray(frames_per_block*4) 111 | for i in range(len(jpeg_group)): 112 | item = jpeg_group[i][0] 113 | table[(i*4)+0] = (len(item) >> 0) & 0xFF 114 | table[(i*4)+1] = (len(item) >> 8) & 0xFF 115 | table[(i*4)+2] = (len(item) >> 16) & 0xFF 116 | table[(i*4)+3] = (len(item) >> 24) & 0xFF 117 | 118 | # Write directory sector 119 | fout.write(table) 120 | 121 | # Write each frame out with padding and audio 122 | for (jpg_frame, aud_frame) in jpeg_group: 123 | # Video frame 124 | fout.write(jpg_frame) 125 | 126 | # Pad to nearest 512 byte multiple 127 | size = len(jpg_frame) 128 | pad = size % 512 129 | if pad > 0: 130 | pad = 512 - pad 131 | fout.write(bytearray(pad)) 132 | 133 | # Audio frame 134 | fout.write(aud_frame) 135 | 136 | # Pad to nearest 512 byte multiple 137 | audio_padded_size = (int((audio_block_size + 511) / 512) * 512) 138 | pad = audio_padded_size - len(aud_frame) 139 | if pad > 0: 140 | fout.write(bytearray(pad)) 141 | 142 | jpeg_group = [] 143 | 144 | print ("\nEnd of conversion") 145 | 146 | if __name__ == "__main__": 147 | main(sys.argv[1:]) -------------------------------------------------------------------------------- /scripts/legacy/README.md: -------------------------------------------------------------------------------- 1 | ## Scripts 2 | 3 | Convert various video input file formats to a MJPEG container format supported by FPGAmp (requires ffmpeg) 4 | 5 | ``` 6 | 7 | # Convert input video file (input.avi) to 800x600 and split to JPEG stream (output.video) and audio PCM stream (output.audio) 8 | ./convert_ffmpeg.py input.avi 9 | 10 | # Combine JPEG stream and audio PCM stream into MJPEG container 11 | ./convert_mjpeg.py -i output.video -a output.audio -o output.mjpg 12 | 13 | # ... Copy output.mjpg to the SD/MMC card so that it is playable... 14 | ``` 15 | -------------------------------------------------------------------------------- /scripts/legacy/convert_ffmpeg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | 5 | ################################################################## 6 | # Main 7 | ################################################################## 8 | def main(argv): 9 | 10 | inputfile = '' 11 | try: 12 | inputfile = argv[0] 13 | except: 14 | print('No files specified') 15 | sys.exit(2) 16 | 17 | print("# Convert to MP4 (scaled to 800x600)") 18 | os.system("ffmpeg -i %s -vf scale=800x600 output.mp4" % inputfile) 19 | 20 | print("# Convert video to JPEG stream") 21 | os.system("ffmpeg -i output.mp4 -vcodec mjpeg -f mjpeg pipe:1 > output.video") 22 | 23 | print("# Convert audio to PCM") 24 | os.system("ffmpeg -i output.mp4 -f s16le -acodec pcm_s16le -ar 44100 output.audio") 25 | 26 | if __name__ == "__main__": 27 | main(sys.argv[1:]) 28 | -------------------------------------------------------------------------------- /scripts/legacy/convert_mjpeg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import argparse 4 | import os 5 | 6 | ################################################################## 7 | # Main 8 | ################################################################## 9 | def main(argv): 10 | 11 | input_files = [] 12 | 13 | parser = argparse.ArgumentParser() 14 | parser.add_argument('-i', dest='video', required=True, help='Input JPEG stream') 15 | parser.add_argument('-a', dest='audio', required=True, help='Input audio stream') 16 | parser.add_argument('-o', dest='output', required=True, help='Output file') 17 | args = vars(parser.parse_args()) 18 | 19 | video_file = args['video'] 20 | audio_file = args['audio'] 21 | output_file = args['output'] 22 | 23 | frames_per_block = 128 24 | audio_samples_per_frame = 44100 / 25 25 | 26 | # 16-bit x 2 27 | audio_block_size = int(audio_samples_per_frame * 4) 28 | 29 | # Round up to sector multiple 30 | audio_padded_size = (int((audio_block_size + 511) / 512) * 512) 31 | 32 | fout = open(output_file, 'wb') 33 | f_video = open(video_file, "rb") 34 | f_audio = open(audio_file, "rb") 35 | 36 | # Convert to supported file format 37 | data = f_video.read(1) 38 | last_b = None 39 | found_soi = False 40 | jpeg = bytearray() 41 | jpeg_group = [] 42 | frame_count= 0 43 | print ("Starting conversion") 44 | while data: 45 | jpeg.append(data[0]) 46 | 47 | # Detect SOI 48 | if not found_soi and data == b'\xd8' and last_b == b'\xff': 49 | found_soi = True 50 | # Detect EOI 51 | elif found_soi and data == b'\xd9' and last_b == b'\xff': 52 | found_soi = False 53 | 54 | # Read an audio blob to go with video frame 55 | audio_blob = f_audio.read(audio_block_size) 56 | 57 | # Add video + audio frame tuple to list 58 | jpeg_group.append((jpeg,audio_blob)) 59 | 60 | # Reset JPEG handler 61 | jpeg = bytearray() 62 | 63 | # Progress print 64 | frame_count += 1 65 | if frame_count % 25 == 0: 66 | print ("\rFrame: %d" % frame_count, end='', flush=True) 67 | 68 | last_b = data 69 | 70 | # Read next JPEG stream byte 71 | data = f_video.read(1) 72 | 73 | # End of video stream or 128 video frames reached 74 | if len(jpeg_group) == frames_per_block or not data: 75 | # Build a directory of up-to 512 frames 76 | table = bytearray(frames_per_block*4) 77 | for i in range(len(jpeg_group)): 78 | item = jpeg_group[i][0] 79 | table[(i*4)+0] = (len(item) >> 0) & 0xFF 80 | table[(i*4)+1] = (len(item) >> 8) & 0xFF 81 | table[(i*4)+2] = (len(item) >> 16) & 0xFF 82 | table[(i*4)+3] = (len(item) >> 24) & 0xFF 83 | 84 | # Write directory sector 85 | fout.write(table) 86 | 87 | # Write each frame out with padding and audio 88 | for (jpg_frame, aud_frame) in jpeg_group: 89 | # Video frame 90 | fout.write(jpg_frame) 91 | 92 | # Pad to nearest 512 byte multiple 93 | size = len(jpg_frame) 94 | pad = size % 512 95 | if pad > 0: 96 | pad = 512 - pad 97 | fout.write(bytearray(pad)) 98 | 99 | # Audio frame 100 | fout.write(aud_frame) 101 | 102 | # Pad to nearest 512 byte multiple 103 | pad = audio_padded_size - len(aud_frame) 104 | if pad > 0: 105 | fout.write(bytearray(pad)) 106 | 107 | jpeg_group = [] 108 | 109 | print ("\nEnd of conversion") 110 | 111 | if __name__ == "__main__": 112 | main(sys.argv[1:]) 113 | --------------------------------------------------------------------------------