kopia lustrzana https://github.com/hoglet67/RGBtoHDMI
				
				
				
			Extended calibration to detect Electron
Change-Id: I8893c014b18ac199ecc76d3cec4d89d23e13f76cissue_1022
							rodzic
							
								
									c9c7e5957e
								
							
						
					
					
						commit
						0db1745459
					
				|  | @ -27,11 +27,12 @@ | ||||||
| #define BIT_MODE7        0x01 | #define BIT_MODE7        0x01 | ||||||
| #define BIT_DRAW_BUFFER  0x02 | #define BIT_DRAW_BUFFER  0x02 | ||||||
| #define BIT_DISP_BUFFER  0x04 | #define BIT_DISP_BUFFER  0x04 | ||||||
| #define BIT_FIELD_TYPE   0x08 | #define BIT_ELK          0x08 | ||||||
| #define BIT_PROBE        0x10 | #define BIT_PROBE        0x10 | ||||||
| #define BIT_CALIBRATE    0x20 | #define BIT_CALIBRATE    0x20 | ||||||
| #define BIT_CAL_COUNT    0x40 | #define BIT_CAL_COUNT    0x40 | ||||||
| #define BIT_INITIALIZE   0x80 | #define BIT_INITIALIZE   0x80 | ||||||
|  | #define BIT_FIELD_TYPE   0x100 | ||||||
| 
 | 
 | ||||||
| // R0 return value bits
 | // R0 return value bits
 | ||||||
| #define BIT_CAL          0x02 | #define BIT_CAL          0x02 | ||||||
|  |  | ||||||
|  | @ -113,7 +113,7 @@ rgb_to_fb: | ||||||
|         bleq   clear_screen |         bleq   clear_screen | ||||||
| 
 | 
 | ||||||
|         // clear all the state bits apart from the following: |         // clear all the state bits apart from the following: | ||||||
|         bic    r3, r3, #~(BIT_MODE7 | BIT_PROBE | BIT_CALIBRATE | BIT_CAL_COUNT | BIT_INITIALIZE) |         bic    r3, r3, #~(BIT_MODE7 | BIT_PROBE | BIT_CALIBRATE | BIT_CAL_COUNT | BIT_INITIALIZE | BIT_ELK) | ||||||
| 
 | 
 | ||||||
|         // write to buffer 0, display buffer 1 |         // write to buffer 0, display buffer 1 | ||||||
|         orr    r3, r3, #BIT_DISP_BUFFER |         orr    r3, r3, #BIT_DISP_BUFFER | ||||||
|  | @ -190,6 +190,8 @@ frame: | ||||||
|         // Correct the relative positions of the odd and even frames |         // Correct the relative positions of the odd and even frames | ||||||
|         // In Mode 0..6, reduce the number of active lines by one for the even frame |         // In Mode 0..6, reduce the number of active lines by one for the even frame | ||||||
|         // In Mode 7, increment the frame buffer pointer by one line for the even field |         // In Mode 7, increment the frame buffer pointer by one line for the even field | ||||||
|  |         tst    r3, #BIT_ELK | ||||||
|  |         bne    skip_line_loop | ||||||
|         tst    r3, #BIT_FIELD_TYPE |         tst    r3, #BIT_FIELD_TYPE | ||||||
|         beq    skip_line_loop |         beq    skip_line_loop | ||||||
|         tst    r3, #BIT_MODE7 |         tst    r3, #BIT_MODE7 | ||||||
|  |  | ||||||
|  | @ -346,7 +346,7 @@ void init_hardware() { | ||||||
| static char last[SCREEN_HEIGHT * 336] __attribute__((aligned(32))); | static char last[SCREEN_HEIGHT * 336] __attribute__((aligned(32))); | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| int diff_N_frames(int sp, int n, int mode7, int chars_per_line) { | int diff_N_frames(int sp, int n, int mode7, int elk, int chars_per_line) { | ||||||
| 
 | 
 | ||||||
|    int sum = 0; |    int sum = 0; | ||||||
|    int min = INT_MAX; |    int min = INT_MAX; | ||||||
|  | @ -361,7 +361,7 @@ int diff_N_frames(int sp, int n, int mode7, int chars_per_line) { | ||||||
| 
 | 
 | ||||||
|    // In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field)
 |    // In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field)
 | ||||||
|    // In mode 7, set BIT_CAL_COUNT to 0 (capture two fields, doesn't matter whether odd-even or even-odd)
 |    // In mode 7, set BIT_CAL_COUNT to 0 (capture two fields, doesn't matter whether odd-even or even-odd)
 | ||||||
|    unsigned int flags = mode7 | BIT_CALIBRATE | (mode7 ? 0 : BIT_CAL_COUNT); |    unsigned int flags = mode7 | BIT_CALIBRATE | (mode7 ? 0 : BIT_CAL_COUNT) | (elk ? BIT_ELK : 0); | ||||||
| 
 | 
 | ||||||
| #ifdef INSTRUMENT_CAL | #ifdef INSTRUMENT_CAL | ||||||
|    t = _get_cycle_counter(); |    t = _get_cycle_counter(); | ||||||
|  | @ -428,7 +428,7 @@ int diff_N_frames(int sp, int n, int mode7, int chars_per_line) { | ||||||
|    return sum; |    return sum; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int total_N_frames(int sp, int n, int mode7, int chars_per_line) { | int total_N_frames(int sp, int n, int mode7, int elk, int chars_per_line) { | ||||||
| 
 | 
 | ||||||
|    int sum = 0; |    int sum = 0; | ||||||
|    int min = INT_MAX; |    int min = INT_MAX; | ||||||
|  | @ -442,7 +442,7 @@ int total_N_frames(int sp, int n, int mode7, int chars_per_line) { | ||||||
| 
 | 
 | ||||||
|    // In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field)
 |    // In mode 0..6, set BIT_CAL_COUNT to 1 (capture 1 field)
 | ||||||
|    // In mode 7, set BIT_CAL_COUNT to 0 (capture two fields, doesn't matter whether odd-even or even-odd)
 |    // In mode 7, set BIT_CAL_COUNT to 0 (capture two fields, doesn't matter whether odd-even or even-odd)
 | ||||||
|    unsigned int flags = mode7 | BIT_CALIBRATE | (mode7 ? 0 : BIT_CAL_COUNT); |    unsigned int flags = mode7 | BIT_CALIBRATE | (mode7 ? 0 : BIT_CAL_COUNT) | (elk ? BIT_ELK : 0); | ||||||
| 
 | 
 | ||||||
|    for (int i = 0; i < n; i++) { |    for (int i = 0; i < n; i++) { | ||||||
|       int total = 0; |       int total = 0; | ||||||
|  | @ -488,19 +488,21 @@ int total_N_frames(int sp, int n, int mode7, int chars_per_line) { | ||||||
|    return sum; |    return sum; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void calibrate_sampling(int mode7, int chars_per_line) { |  | ||||||
|    int i; |  | ||||||
|    int j; |  | ||||||
|    int min_i; |  | ||||||
|    int min_metric; |  | ||||||
|    int metric; |  | ||||||
| 
 |  | ||||||
| // Wait for the cal button to be released
 | // Wait for the cal button to be released
 | ||||||
|  | void wait_for_cal_release() { | ||||||
|    int cal_bit = 0; |    int cal_bit = 0; | ||||||
|    do { |    do { | ||||||
|       cal_bit = ((*(volatile uint32_t *)(PERIPHERAL_BASE + 0x200034)) >> CAL_PIN) & 1; |       cal_bit = ((*(volatile uint32_t *)(PERIPHERAL_BASE + 0x200034)) >> CAL_PIN) & 1; | ||||||
|       log_debug("cal_bit = %d", cal_bit); |       log_debug("cal_bit = %d", cal_bit); | ||||||
|    } while (cal_bit == 0); |    } while (cal_bit == 0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void calibrate_sampling(int mode7, int elk, int chars_per_line) { | ||||||
|  |    int i; | ||||||
|  |    int j; | ||||||
|  |    int min_i; | ||||||
|  |    int min_metric; | ||||||
|  |    int metric; | ||||||
| 
 | 
 | ||||||
|    if (mode7) { |    if (mode7) { | ||||||
|       log_info("Calibrating mode 7"); |       log_info("Calibrating mode 7"); | ||||||
|  | @ -512,7 +514,7 @@ void calibrate_sampling(int mode7, int chars_per_line) { | ||||||
|             sp_mode7[j] = i; |             sp_mode7[j] = i; | ||||||
|          } |          } | ||||||
|          init_sampling_point_register(sp_mode7, sp_default); |          init_sampling_point_register(sp_mode7, sp_default); | ||||||
|          metric = diff_N_frames(i, NUM_CAL_FRAMES, mode7, chars_per_line); |          metric = diff_N_frames(i, NUM_CAL_FRAMES, mode7, elk, chars_per_line); | ||||||
|          if (metric < min_metric) { |          if (metric < min_metric) { | ||||||
|             min_metric = metric; |             min_metric = metric; | ||||||
|             min_i = i; |             min_i = i; | ||||||
|  | @ -534,13 +536,13 @@ void calibrate_sampling(int mode7, int chars_per_line) { | ||||||
|          if (sp_mode7[i] > 0) { |          if (sp_mode7[i] > 0) { | ||||||
|             sp_mode7[i]--; |             sp_mode7[i]--; | ||||||
|             init_sampling_point_register(sp_mode7, sp_default); |             init_sampling_point_register(sp_mode7, sp_default); | ||||||
|             left = diff_N_frames(i, NUM_CAL_FRAMES, mode7, chars_per_line);             |             left = diff_N_frames(i, NUM_CAL_FRAMES, mode7, elk, chars_per_line); | ||||||
|             sp_mode7[i]++; |             sp_mode7[i]++; | ||||||
|          } |          } | ||||||
|          if (sp_mode7[i] < 7) { |          if (sp_mode7[i] < 7) { | ||||||
|             sp_mode7[i]++; |             sp_mode7[i]++; | ||||||
|             init_sampling_point_register(sp_mode7, sp_default); |             init_sampling_point_register(sp_mode7, sp_default); | ||||||
|             right = diff_N_frames(i, NUM_CAL_FRAMES, mode7, chars_per_line); |             right = diff_N_frames(i, NUM_CAL_FRAMES, mode7, elk, chars_per_line); | ||||||
|             sp_mode7[i]--; |             sp_mode7[i]--; | ||||||
|          } |          } | ||||||
|          if (left < right && left < ref) { |          if (left < right && left < ref) { | ||||||
|  | @ -562,7 +564,7 @@ void calibrate_sampling(int mode7, int chars_per_line) { | ||||||
|       min_i = 0; |       min_i = 0; | ||||||
|       for (i = 0; i <= 5; i++) { |       for (i = 0; i <= 5; i++) { | ||||||
|          init_sampling_point_register(sp_mode7, i); |          init_sampling_point_register(sp_mode7, i); | ||||||
|          metric = diff_N_frames(i, NUM_CAL_FRAMES, mode7, chars_per_line); |          metric = diff_N_frames(i, NUM_CAL_FRAMES, mode7, elk, chars_per_line); | ||||||
|          if (metric < min_metric) { |          if (metric < min_metric) { | ||||||
|             min_metric = metric; |             min_metric = metric; | ||||||
|             min_i = i; |             min_i = i; | ||||||
|  | @ -574,7 +576,54 @@ void calibrate_sampling(int mode7, int chars_per_line) { | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | int test_for_elk(int mode7, int chars_per_line) { | ||||||
|  | 
 | ||||||
|  |    // If mode 7, then assume the Beeb
 | ||||||
|  |    if (mode7) { | ||||||
|  |       return 0; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    unsigned int flags = BIT_CALIBRATE | BIT_CAL_COUNT; | ||||||
|  |    unsigned char *fb1 = fb; | ||||||
|  |    unsigned char *fb2 = fb + SCREEN_HEIGHT * pitch; | ||||||
|  | 
 | ||||||
|  |    // Grab one field
 | ||||||
|  |    rgb_to_fb(fb1, chars_per_line, pitch, flags); | ||||||
|  | 
 | ||||||
|  |    // Grab second field
 | ||||||
|  |    rgb_to_fb(fb2, chars_per_line, pitch, flags); | ||||||
|  | 
 | ||||||
|  |    unsigned int min_diff = INT_MAX; | ||||||
|  |    unsigned int min_offset = 0; | ||||||
|  | 
 | ||||||
|  |    for (int offset = -2; offset <= 2; offset += 2) { | ||||||
|  | 
 | ||||||
|  |       uint32_t *p1 = (uint32_t *)(fb1 + 2 * pitch); | ||||||
|  |       uint32_t *p2 = (uint32_t *)(fb2 + 2 * pitch + offset * pitch); | ||||||
|  |       unsigned int diff = 0; | ||||||
|  |       for (int i = 0; i < (SCREEN_HEIGHT - 4) * pitch; i += 4) { | ||||||
|  |          uint32_t d = (*p1++) ^ (*p2++); | ||||||
|  |          while (d) { | ||||||
|  |             if (d & 0x0F) { | ||||||
|  |                diff++; | ||||||
|  |             } | ||||||
|  |             d >>= 4; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |       if (diff < min_diff) { | ||||||
|  |          min_diff = diff; | ||||||
|  |          min_offset = offset; | ||||||
|  |       } | ||||||
|  |       log_debug("offset = %d, diff = %u", offset, diff); | ||||||
|  | 
 | ||||||
|  |    } | ||||||
|  |    log_debug("min offset = %d", min_offset); | ||||||
|  |    return min_offset != 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| void rgb_to_hdmi_main() { | void rgb_to_hdmi_main() { | ||||||
|  |    int elk; | ||||||
|    int mode7; |    int mode7; | ||||||
|    int last_mode7; |    int last_mode7; | ||||||
|    int result; |    int result; | ||||||
|  | @ -586,6 +635,7 @@ void rgb_to_hdmi_main() { | ||||||
| 
 | 
 | ||||||
|    // Determine initial mode
 |    // Determine initial mode
 | ||||||
|    mode7 = rgb_to_fb(fb, 0, 0, BIT_PROBE); |    mode7 = rgb_to_fb(fb, 0, 0, BIT_PROBE); | ||||||
|  |    elk = 0; | ||||||
| 
 | 
 | ||||||
|    while (1) { |    while (1) { | ||||||
|       log_debug("Setting mode7 = %d", mode7); |       log_debug("Setting mode7 = %d", mode7); | ||||||
|  | @ -600,12 +650,15 @@ void rgb_to_hdmi_main() { | ||||||
|       do { |       do { | ||||||
| 
 | 
 | ||||||
|          log_debug("Entering rgb_to_fb"); |          log_debug("Entering rgb_to_fb"); | ||||||
|          result = rgb_to_fb(fb, chars_per_line, pitch, mode7 | BIT_INITIALIZE); |          result = rgb_to_fb(fb, chars_per_line, pitch, mode7 | BIT_INITIALIZE | (elk ? BIT_ELK : 0)); | ||||||
|          log_debug("Leaving rgb_to_fb, result= %d", result); |          log_debug("Leaving rgb_to_fb, result= %d", result); | ||||||
| 
 | 
 | ||||||
|          if (result & BIT_CAL) { |          if (result & BIT_CAL) { | ||||||
|  |             wait_for_cal_release(); | ||||||
|  |             elk = test_for_elk(mode7, chars_per_line); | ||||||
|  |             log_debug("Elk mode = %d", elk); | ||||||
|             for (int c = 0; c < NUM_CAL_PASSES; c++) { |             for (int c = 0; c < NUM_CAL_PASSES; c++) { | ||||||
|                calibrate_sampling(mode7, chars_per_line); |                calibrate_sampling(mode7, elk, chars_per_line); | ||||||
|             } |             } | ||||||
|          } |          } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Ładowanie…
	
		Reference in New Issue
	
	 David Banks
						David Banks