📄 alt_video_display.c
字号:
/******************************************************************************* ** License Agreement ** ** Copyright (c) 2007 Altera Corporation, San Jose, California, USA. ** All rights reserved. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and associated documentation files (the "Software"), ** to deal in the Software without restriction, including without limitation ** the rights to use, copy, modify, merge, publish, distribute, sublicense, ** and/or sell copies of the Software, and to permit persons to whom the ** Software is furnished to do so, subject to the following conditions: ** ** The above copyright notice and this permission notice shall be included in ** all copies or substantial portions of the Software. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE ** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING ** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ** DEALINGS IN THE SOFTWARE. ** ** This agreement shall be governed in all respects by the laws of the State ** of California and by the laws of the United States of America. ** *******************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <io.h>#include <sys/alt_cache.h>#include <malloc.h>#include <priv/alt_file.h>#include <sys/alt_irq.h>#include <altera_avalon_sgdma.h>#include <altera_avalon_sgdma_descriptor.h>#include <altera_avalon_sgdma_regs.h>#include "system.h"#include "alt_video_display.h"/******************************************************************* PUBLIC API FUNCTIONS *******************************************************************/ /******************************************************************* Function: alt_video_display_init** Purpose: Initializes the display controller. Gets memory for the * frame buffer and descriptor buffers, intitalizes the * descriptors, sets the resolution of the frame buffers,* clears all the frame buffers, then finally opens * the SGDMA, registers the SGDMA callback function and* starts the SGDMA.* * Returns: *Note non-standard return code!*:* Pointer to the display controller structure, or NULL on failure.******************************************************************/alt_video_display* alt_video_display_init( char* sgdma_name, int width, int height, int color_depth, int buffer_location, int descriptor_location, int num_buffers){ alt_video_display* display; unsigned int bytes_per_pixel, bytes_per_frame, descriptors_per_frame, i; int result; // We'll need these values more than once, so let's pre-calculate them. bytes_per_pixel = color_depth >> 3; // same as /8 bytes_per_frame = (( width * height ) * bytes_per_pixel ); // Calculate the number of descriptors needed for each frame if( bytes_per_frame <= ALT_VIDEO_DISPLAY_BYTES_PER_DESC ) { descriptors_per_frame = 1; } else if(( bytes_per_frame % ALT_VIDEO_DISPLAY_BYTES_PER_DESC) == 0) { descriptors_per_frame = bytes_per_frame / ALT_VIDEO_DISPLAY_BYTES_PER_DESC; } else { descriptors_per_frame = ( bytes_per_frame / ALT_VIDEO_DISPLAY_BYTES_PER_DESC ) + 1; } // Check for too many frame buffers if( num_buffers > ALT_VIDEO_DISPLAY_MAX_BUFFERS ) { num_buffers = ALT_VIDEO_DISPLAY_MAX_BUFFERS; } // Allocate our display struct display = (alt_video_display*) malloc(sizeof(alt_video_display)); if(!display) { return NULL; } // Fill out the display structure display->width = width; display->height = height; display->color_depth = color_depth; display->num_frame_buffers = num_buffers; display->bytes_per_frame = bytes_per_frame; display->bytes_per_pixel = bytes_per_pixel; display->buffer_being_displayed = 0; display->buffer_being_written = (num_buffers > 1) ? 1:0; display->descriptors_per_frame = descriptors_per_frame; // Allocate our frame and descriptor buffers if(alt_video_display_allocate_buffers( display, bytes_per_frame, buffer_location, descriptor_location, num_buffers ) ) { return NULL; } // Now construct SGDMA descriptors for each frame buffer for( i = 0; i < num_buffers; i++ ) { alt_video_display_setup_frame_descriptors( display, // our display display->buffer_ptrs[i], // frame display->buffer_ptrs[i]->buffer, // frame location display->buffer_ptrs[i]->desc_base ); // descriptor memory } // Clear all frame buffers to black for( i = 0; i < num_buffers; i++ ) { memset( (void*)(display->buffer_ptrs[i]->buffer), ALT_VIDEO_DISPLAY_BLACK_8, display->bytes_per_frame ); } // Open the SGDMA display->sgdma = alt_avalon_sgdma_open(sgdma_name); if(!display->sgdma) { return NULL; } /* Enable SGDMA "parking" mode */ IOWR_ALTERA_AVALON_SGDMA_CONTROL(LCD_SGDMA_BASE, ALTERA_AVALON_SGDMA_CONTROL_PARK_MSK); /* Now start the SGDMA */ result = alt_avalon_sgdma_do_async_transfer( display->sgdma, display->buffer_ptrs[display->buffer_being_displayed]->desc_base); if(result) { return NULL; } return ( display );}/******************************************************************* Function: alt_video_display_close** Purpose: Closes the display and frees all malloc'd memory** Returns: void *******************************************************************/void alt_video_display_close( alt_video_display* display, int buffer_location, int descriptor_location ){ int i; // Stop the sgdma alt_avalon_sgdma_stop( display->sgdma ); // Free our frame buffers and descriptor buffers for( i = 0; i < display->num_frame_buffers; i++ ) { // Free the frame buffer if it was on the heap if( buffer_location == ALT_VIDEO_DISPLAY_USE_HEAP ) free( display->buffer_ptrs[i]->buffer ); // Free the descriptor buffer it was on the heap if( descriptor_location == ALT_VIDEO_DISPLAY_USE_HEAP ) free( display->buffer_ptrs[i]->desc_base ); // Free the buffer pointer struct free( display->buffer_ptrs[i] ); } // Finally free our display struct free( display );}/******************************************************************* Function: alt_video_display_register_written_buffer** Purpose: Registers the buffer pointed to by buffer_being_written* as being finished and ready for display.** Returns: 0 - Everything is groovy.* 1 - buffer_being_written is now equal to buffer_being_displayed* - It would be a good idea to wait for buffer_being_displayed * to increment before writing to buffer_being_written.*******************************************************************/int alt_video_display_register_written_buffer( alt_video_display* display ){ int ret_code, prev_frame_index; alt_sgdma_descriptor *desc_prev_frame_tail; alt_sgdma_descriptor *desc_being_registered_head, *desc_being_registered_tail; /* * Prepare relevant SGDMA descriptors in the frame being registered: * - Set the new frame's head-descriptor transfer count to 0 * - Ensure that the new frame descriptor chain loops (tail points to head) * - Point the previous frame at the new one to "break" its loop */ desc_being_registered_head = display->buffer_ptrs[display->buffer_being_written]->desc_base; desc_being_registered_tail = desc_being_registered_head + (display->descriptors_per_frame - 1); IOWR_16DIRECT( (alt_u32)(&desc_being_registered_head->actual_bytes_transferred), 0, (alt_u16) 0x0); IOWR_32DIRECT((alt_u32)(&desc_being_registered_tail->next), 0, (alt_u32)(desc_being_registered_head)); /* Find the tail of the descriptor chain in the last frame registered */ prev_frame_index = (display->buffer_being_written - 1); if(prev_frame_index < 0) { prev_frame_index = (display->num_frame_buffers - 1); } desc_prev_frame_tail = display->buffer_ptrs[prev_frame_index]->desc_base; desc_prev_frame_tail += (display->descriptors_per_frame - 1); IOWR_32DIRECT((alt_u32)(&desc_prev_frame_tail->next), 0, (alt_u32)(desc_being_registered_head)); /* * Update frame_being_written index. Note: The new index may *not* be * safe to write to; alt_video_display_buffer_is_available() must be * called to verify this). */ display->buffer_being_written = ( display->buffer_being_written + 1 ) % display->num_frame_buffers; if( display->buffer_being_written == display->buffer_being_displayed ) { ret_code = 1; } else { ret_code = 0; } return(ret_code);}/******************************************************************* Function: alt_video_display_buffer_is_available*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -