Commit adf3c494 authored by Daniel Fort's avatar Daniel Fort
Browse files

Merged unified into update-to-700D.115

--HG--
branch : update-to-700D.115
......@@ -184,7 +184,7 @@ static void cmos16_log(breakpoint_t *bkpt)
void adtg_log_task()
{
adtg_buf_pos_max = 128 * 1024;
adtg_buf = fio_malloc(adtg_buf_pos_max * 4 + 0x100);
adtg_buf = malloc(adtg_buf_pos_max * 4 + 0x100);
if(!adtg_buf)
{
......@@ -253,7 +253,7 @@ void adtg_log_task()
/* free buffer */
void *buf = adtg_buf;
adtg_buf = NULL;
fio_free(buf);
free(buf);
}
static MENU_SELECT_FUNC(adtg_log_toggle)
......
......@@ -90,9 +90,11 @@ static void mem_test_bmp_fill(int arg0, int arg1, int arg2, int arg3)
static void mem_test_edmac_copy_rectangle(int arg0, int arg1, int arg2, int arg3)
{
uint8_t* real = bmp_vram_real();
uint8_t* idle = bmp_vram_idle();
edmac_copy_rectangle_adv(BMP_VRAM_START(idle), BMP_VRAM_START(real), 960, 0, 0, 960, 0, 0, 720, 480);
uint8_t* real = BMP_VRAM_START(bmp_vram_real());
uint8_t* idle = BMP_VRAM_START(bmp_vram_idle());
/* careful - do not mix cacheable and uncacheable pointers unless you know what you are doing */
edmac_copy_rectangle_adv(UNCACHEABLE(idle), UNCACHEABLE(real), 960, 0, 0, 960, 0, 0, 720, 480);
}
static uint64_t FAST DUMP_ASM mem_test_read64(uint64_t* buf, uint32_t n)
......@@ -146,8 +148,8 @@ static void mem_benchmark_task()
void* buf1 = 0;
void* buf2 = 0;
buf1 = tmp_malloc(bufsize);
buf2 = tmp_malloc(bufsize);
buf1 = fio_malloc(bufsize);
buf2 = fio_malloc(bufsize);
if (!buf1 || !buf2)
{
bmp_printf(FONT_LARGE, 0, 0, "malloc error :(");
......@@ -177,7 +179,7 @@ static void mem_benchmark_task()
if (HAS_EDMAC_MEMCPY)
{
mem_benchmark_run("edmac_memcpy ", &y, bufsize, (mem_bench_fun)edmac_memcpy, (intptr_t)buf1, (intptr_t)buf2, bufsize, 0);
mem_benchmark_run("edmac_memcpy ", &y, bufsize, (mem_bench_fun)edmac_memcpy, (intptr_t)UNCACHEABLE(buf1), (intptr_t)UNCACHEABLE(buf2), bufsize, 0);
mem_benchmark_run("edmac_copy_rectangle", &y, 720*480, (mem_bench_fun)mem_test_edmac_copy_rectangle, 0, 0, 0, 0);
}
......@@ -199,6 +201,6 @@ static void mem_benchmark_task()
canon_gui_enable_front_buffer(0);
cleanup:
if (buf1) tmp_free(buf1);
if (buf2) tmp_free(buf2);
if (buf1) free(buf1);
if (buf2) free(buf2);
}
......@@ -541,7 +541,7 @@ static void reverse_bytes_order(void* buf, int count)
}
}
static const char* module_get_string(const char* name)
const char* module_get_string(int module, const char* name)
{
module_strpair_t *strings = &__module_strings_MODULE_NAME[0];
......@@ -587,7 +587,7 @@ static int is_file(const char* filename)
int main(int argc, char** argv)
{
printf("cr2hdr: a post processing tool for Dual ISO images\n\n");
printf("Last update: %s\n", module_get_string("Last update"));
printf("Last update: %s\n", module_get_string(0, "Last update"));
fast_randn_init();
......
......@@ -1612,6 +1612,73 @@ static void init_mlv_chunk_headers(struct raw_info * raw_info)
mlv_fill_wbal(&wbal_hdr, mlv_start_timestamp);
}
static int write_mlv_vers_blocks(FILE *f)
{
int mod = -1;
int error = 0;
do
{
/* get next loaded module id */
mod = module_get_next_loaded(mod);
/* make sure thats a valid one */
if(mod >= 0)
{
/* fetch information from module loader */
const char *mod_name = module_get_name(mod);
const char *mod_build_date = module_get_string(mod, "Build date");
const char *mod_last_update = module_get_string(mod, "Last update");
if(mod_name != NULL)
{
/* just in case that ever happens */
if(mod_build_date == NULL)
{
mod_build_date = "(no build date)";
}
if(mod_last_update == NULL)
{
mod_last_update = "(no version)";
}
/* separating the format string allows us to measure its length for malloc */
const char *fmt_string = "%s built %s; commit %s";
int buf_length = strlen(fmt_string) + strlen(mod_name) + strlen(mod_build_date) + strlen(mod_last_update) + 1;
char *version_string = malloc(buf_length);
/* now build the string */
snprintf(version_string, buf_length, fmt_string, mod_name, mod_build_date, mod_last_update);
/* and finally remove any newlines, they are annoying */
for(unsigned int pos = 0; pos < strlen(version_string); pos++)
{
if(version_string[pos] == '\n')
{
version_string[pos] = ' ';
}
}
/* let the mlv helpers build the block for us */
mlv_vers_hdr_t *hdr = NULL;
mlv_build_vers(&hdr, mlv_start_timestamp, version_string);
/* try to write to output file */
if(FIO_WriteFile(f, hdr, hdr->blockSize) != (int)hdr->blockSize)
{
error = 1;
}
/* free both temporary string and allocated mlv block */
free(version_string);
free(hdr);
}
}
} while(mod >= 0 && !error);
return error;
}
static int write_mlv_chunk_headers(FILE* f)
{
if (FIO_WriteFile(f, &file_hdr, file_hdr.blockSize) != (int)file_hdr.blockSize) return 0;
......@@ -1621,7 +1688,9 @@ static int write_mlv_chunk_headers(FILE* f)
if (FIO_WriteFile(f, &lens_hdr, lens_hdr.blockSize) != (int)lens_hdr.blockSize) return 0;
if (FIO_WriteFile(f, &rtci_hdr, rtci_hdr.blockSize) != (int)rtci_hdr.blockSize) return 0;
if (FIO_WriteFile(f, &wbal_hdr, wbal_hdr.blockSize) != (int)wbal_hdr.blockSize) return 0;
int hdr_size = sizeof(file_hdr) + sizeof(rawi_hdr) + sizeof(idnt_hdr) + sizeof(expo_hdr) + sizeof(lens_hdr) + sizeof(rtci_hdr) + sizeof(wbal_hdr);
if (write_mlv_vers_blocks(f)) return 0;
int hdr_size = FIO_SeekSkipFile(f, 0, SEEK_CUR);
/* insert a null block so the header size is multiple of 512 bytes */
mlv_hdr_t nul_hdr;
......
......@@ -155,6 +155,23 @@ void mlv_fill_idnt(mlv_idnt_hdr_t *hdr, uint64_t start_timestamp)
trace_write(raw_rec_trace_ctx, "[IDNT] cameraName: '%s' cameraModel: 0x%08X cameraSerial: '%s'", hdr->cameraName, hdr->cameraModel, hdr->cameraSerial);
}
void mlv_build_vers(mlv_vers_hdr_t **hdr, uint64_t start_timestamp, const char *version_string)
{
int block_length = strlen(version_string) + sizeof(mlv_vers_hdr_t);
mlv_vers_hdr_t *header = malloc(block_length);
/* prepare header */
mlv_set_type((mlv_hdr_t *)header, "VERS");
mlv_set_timestamp((mlv_hdr_t *)header, start_timestamp);
header->blockSize = block_length;
header->length = strlen(version_string);
char *vers_hdr_payload = (char *)&header[1];
strcpy(vers_hdr_payload, version_string);
*hdr = header;
}
uint64_t mlv_prng_lfsr(uint64_t value)
{
uint64_t lfsr = value;
......
......@@ -231,10 +231,21 @@ typedef struct {
uint32_t blockSize;
uint64_t timestamp;
uint32_t type; /* debug data type, for now 0 - text log */
uint32_t length; /* data can be of arbitrary length and blocks are padded to 32 bits, so store real length */
uint32_t length; /* to allow that data can be of arbitrary length and blocks are padded to 32 bits, so store real length */
/* uint8_t stringData[variable]; */
} mlv_debg_hdr_t;
typedef struct {
uint8_t blockType[4]; /* VERS - Version information block, appears once per module */
uint32_t blockSize;
uint64_t timestamp;
uint32_t length; /* to allow that data can be of arbitrary length and blocks are padded to 32 bits, so store real length */
/* uint8_t stringData[variable]; // Version string, e.g. "ml-core 20130912", "mlv_rec v2.1" or "mlv_lite 0d3fbdaf crop_rec_8k"
// general format "<module_name> <version_information>"
// where <module_name> must not contain spaces whereas <version_information> may be of any characters in UTF-8 format
*/
} mlv_vers_hdr_t;
#pragma pack(pop)
/* helper routines for filling structures from generic camera information */
......@@ -244,6 +255,7 @@ void mlv_fill_lens(mlv_lens_hdr_t *hdr, uint64_t start_timestamp);
void mlv_fill_idnt(mlv_idnt_hdr_t *hdr, uint64_t start_timestamp);
void mlv_fill_wbal(mlv_wbal_hdr_t *hdr, uint64_t start_timestamp);
void mlv_fill_styl(mlv_styl_hdr_t *hdr, uint64_t start_timestamp);
void mlv_build_vers(mlv_vers_hdr_t **hdr, uint64_t start_timestamp, const char *version_string);
/* randomize the 64 bits passed in parameter using LFSR */
uint64_t mlv_prng_lfsr(uint64_t value);
......
......@@ -2904,6 +2904,61 @@ read_headers:
free(buf);
}
}
else if(!memcmp(buf.blockType, "VERS", 4))
{
mlv_vers_hdr_t block_hdr;
int32_t hdr_size = MIN(sizeof(mlv_vers_hdr_t), buf.blockSize);
if(fread(&block_hdr, hdr_size, 1, in_file) != 1)
{
print_msg(MSG_ERROR, "File ends in the middle of a block\n");
goto abort;
}
lua_handle_hdr(lua_state, buf.blockType, &block_hdr, sizeof(block_hdr));
/* get the string length and malloc a buffer for that string */
int str_length = block_hdr.blockSize - hdr_size;
if(str_length)
{
char *buf = malloc(str_length + 1);
if(fread(buf, str_length, 1, in_file) != 1)
{
free(buf);
print_msg(MSG_ERROR, "File ends in the middle of a block\n");
goto abort;
}
if(verbose)
{
buf[block_hdr.length] = '\000';
print_msg(MSG_INFO, " String: '%s'\n", buf);
}
/* only output this block if there is any data */
if(mlv_output && !no_metadata_mode)
{
/* correct header size if needed */
block_hdr.blockSize = sizeof(mlv_vers_hdr_t) + str_length;
if(fwrite(&block_hdr, sizeof(mlv_vers_hdr_t), 1, out_file) != 1)
{
free(buf);
print_msg(MSG_ERROR, "Failed writing into .MLV file\n");
goto abort;
}
if(fwrite(buf, str_length, 1, out_file) != 1)
{
free(buf);
print_msg(MSG_ERROR, "Failed writing into .MLV file\n");
goto abort;
}
}
free(buf);
}
}
else if(!memcmp(buf.blockType, "ELVL", 4))
{
mlv_elvl_hdr_t block_hdr;
......
......@@ -2527,6 +2527,73 @@ static uint32_t raw_get_next_filenum()
return fileNum;
}
static int write_mlv_vers_blocks(FILE *f)
{
int mod = -1;
int error = 0;
do
{
/* get next loaded module id */
mod = module_get_next_loaded(mod);
/* make sure thats a valid one */
if(mod >= 0)
{
/* fetch information from module loader */
const char *mod_name = module_get_name(mod);
const char *mod_build_date = module_get_string(mod, "Build date");
const char *mod_last_update = module_get_string(mod, "Last update");
if(mod_name != NULL)
{
/* just in case that ever happens */
if(mod_build_date == NULL)
{
mod_build_date = "(no build date)";
}
if(mod_last_update == NULL)
{
mod_last_update = "(no version)";
}
/* separating the format string allows us to measure its length for malloc */
const char *fmt_string = "%s built %s; commit %s";
int buf_length = strlen(fmt_string) + strlen(mod_name) + strlen(mod_build_date) + strlen(mod_last_update) + 1;
char *version_string = malloc(buf_length);
/* now build the string */
snprintf(version_string, buf_length, fmt_string, mod_name, mod_build_date, mod_last_update);
/* and finally remove any newlines, they are annoying */
for(unsigned int pos = 0; pos < strlen(version_string); pos++)
{
if(version_string[pos] == '\n')
{
version_string[pos] = ' ';
}
}
/* let the mlv helpers build the block for us */
mlv_vers_hdr_t *hdr = NULL;
mlv_build_vers(&hdr, mlv_start_timestamp, version_string);
/* try to write to output file */
if(FIO_WriteFile(f, hdr, hdr->blockSize) != (int)hdr->blockSize)
{
error = 1;
}
/* free both temporary string and allocated mlv block */
free(version_string);
free(hdr);
}
}
} while(mod >= 0 && !error);
return error;
}
static void raw_prepare_chunk(FILE *f, mlv_file_hdr_t *hdr)
{
if(f == NULL)
......@@ -2570,6 +2637,7 @@ static void raw_prepare_chunk(FILE *f, mlv_file_hdr_t *hdr)
mlv_write_hdr(f, (mlv_hdr_t *)&idnt_hdr);
mlv_write_hdr(f, (mlv_hdr_t *)&wbal_hdr);
mlv_write_hdr(f, (mlv_hdr_t *)&styl_hdr);
write_mlv_vers_blocks(f);
}
}
......
......@@ -30,6 +30,7 @@
#include <beep.h>
#include <propvalues.h>
#include <raw.h>
#include "ml-cbr.h"
#include "../trace/trace.h"
#include "../mlv_rec/mlv.h"
......@@ -44,11 +45,6 @@ static CONFIG_INT("mlv.snd.bit.depth", mlv_snd_in_bits_per_sample, 16);
static CONFIG_INT("mlv.snd.sample.rate", mlv_snd_in_sample_rate, 48000);
static CONFIG_INT("mlv.snd.sample.rate.selection", mlv_snd_rate_sel, 0);
int mlv_snd_is_enabled()
{
return mlv_snd_enabled;
}
extern int StartASIFDMAADC(void *, uint32_t, void *, uint32_t, void (*)(), uint32_t);
extern int SetNextASIFADCBuffer(void *, uint32_t);
extern WEAK_FUNC(ret_0) int PowerAudioOutput();
......@@ -104,6 +100,20 @@ audio_data_t *mlv_snd_next_buffer = NULL;
static uint32_t mlv_snd_state = MLV_SND_STATE_IDLE;
/* this tells the audio backend that we are going to record sound */
static ml_cbr_action mlv_snd_snd_rec_cbr (const char *event, void *data)
{
uint32_t *status = (uint32_t*)data;
if(mlv_snd_enabled)
{
*status = 1;
return ML_CBR_STOP;
}
return ML_CBR_CONTINUE;
}
static void mlv_snd_asif_in_cbr()
{
/* the next buffer is now being filled, so update timestamp. do this first to be closer to real start. */
......@@ -633,6 +643,7 @@ MODULE_INFO_END()
MODULE_CBRS_START()
MODULE_CBR(CBR_VSYNC, mlv_snd_vsync, 0)
MODULE_NAMED_CBR("snd_rec_enabled", mlv_snd_snd_rec_cbr)
MODULE_CBRS_END()
MODULE_CONFIGS_START()
......
......@@ -13,6 +13,7 @@
#include <edmac-memcpy.h>
#include <screenshot.h>
#include <powersave.h>
#include <alloca.h>
/* optional routines */
extern WEAK_FUNC(ret_0) uint32_t ml_rpc_send(uint32_t command, uint32_t parm1, uint32_t parm2, uint32_t parm3, uint32_t wait);
......@@ -106,7 +107,7 @@ static void next_tick_cbr(int arg1, void* arg2)
SetHPTimerNextTick(arg1, 100000, timer_cbr, overrun_cbr, 0);
}
#define TEST_MSG(fmt, ...) { if (!stub_silence || !stub_ok) stub_log_len += snprintf(stub_log_buf + stub_log_len, stub_max_log_len - stub_log_len, fmt, ## __VA_ARGS__); printf(fmt, ## __VA_ARGS__); }
#define TEST_MSG(fmt, ...) { if (!stub_silence || !stub_ok) { stub_log_len += snprintf(stub_log_buf + stub_log_len, stub_max_log_len - stub_log_len, fmt, ## __VA_ARGS__); printf(fmt, ## __VA_ARGS__); } }
#define TEST_VOID(x) { x; stub_ok = 1; TEST_MSG(" %s\n", #x); }
#define TEST_FUNC(x) { int ans = (int)(x); stub_ok = 1; TEST_MSG(" %s => 0x%x\n", #x, ans); }
#define TEST_FUNC_CHECK(x, condition) { int ans = (int)(x); stub_ok = ans condition; TEST_MSG("[%s] %s => 0x%x\n", stub_ok ? "Pass" : "FAIL", #x, ans); if (stub_ok) stub_passed_tests++; else stub_failed_tests++; }
......@@ -120,6 +121,299 @@ static int stub_ok = 1;
static int stub_passed_tests = 0;
static int stub_failed_tests = 0;
/* delay with interrupts disabled */
static void busy_wait_ms(int ms)
{
int t0 = get_ms_clock_value();
while (get_ms_clock_value() - t0 < ms)
;
}
/* this checks whether clean_d_cache actually writes the data to physical memory
* so other devices (such as DMA controllers) will see the same memory contents as the CPU */
static void stub_test_cache_bmp()
{
TEST_MSG("Cache test A (EDMAC on BMP buffer)...\n");
void * bmp;
TEST_FUNC_CHECK(bmp = bmp_load("ML/CROPMKS/CINESCO2.BMP", 1), != 0);
if (!bmp) return;
uint8_t * const bvram_mirror = get_bvram_mirror();
if (!bvram_mirror) return;
/* perform the test twice:
* one without cache cleaning, expected to fail,
* and one with cache cleaning, expected to succeed */
for (int k = 0; k < 2; k++)
{
/* perform this test with interrupts disabled */
int old = cli();
int dis = cli();
TEST_FUNC_CHECK(old, != dis);
/* draw a cropmark */
clrscr();
bmp_draw_scaled_ex(bmp, os.x0, os.y0, os.x_ex, os.y_ex, bvram_mirror);
/* copy the image to idle buffer using EDMAC */
uint8_t * src = bmp_vram_real();
uint8_t * dst = bmp_vram_idle();
ASSERT(src == CACHEABLE(src));
ASSERT(dst == CACHEABLE(dst));
if (k == 0)
{
/* trick the copying routine so it doesn't handle caching issues.
* these pointers are actually cacheable (for speed reasons);
* flagging them as uncacheable has no effect on DMA behavior.
* this test should fail. */
src = UNCACHEABLE(src);
}
/* mark destination as uncacheable (the EDMAC routine expects it this way) */
/* this is generally incorrect; you should use fio_malloc instead. */
dst = UNCACHEABLE(dst);
edmac_copy_rectangle_adv_start(dst, src, 960, 0, 0, 960, 0, 0, 720, 480);
/* wait for EDMAC transfer to finish */
/* probably not needed, as take_semaphore will re-enable interrupts */
busy_wait_ms(1000);
/* cleanup EDMAC transfer */
edmac_copy_rectangle_finish();
/* interrupts are disabled again - from DryOS context switch */
/* now compare the image buffers */
int differences = 0;
for (int y = 0; y < 480; y++)
{
for (int x = 0; x < 720; x++)
{
int i = x + y * 960;
if (src[i] != dst[i])
{
differences++;
}
}
}
info_led_on();
busy_wait_ms(1000);
info_led_off();
/* do we still have interrupts disabled? */
int irq = cli();
TEST_FUNC_CHECK(irq, == dis);
if (k)
{
/* expect to succeed */
TEST_FUNC_CHECK(differences, == 0);
}
else
{
/* expect to fail */
TEST_FUNC_CHECK(differences, > 100);
}
/* interrupts no longer needed */
sei(old);
}
}
static int stub_test_cache_fio_do(int handle_cache)
{
/* prefer CF card if present */
char * test_file = is_dir("A:/") ? "A:/test.dat" : "test.dat";
FILE * f;
TEST_FUNC_CHECK(f = FIO_CreateFile(test_file), != 0);
/* result */
int fail = -1;
/* cacheable buffer that will fit the entire cache */
/* placed at some random stack offset */
/* note: we have 32K stack */
const int size = 8192;
uint8_t * pad = alloca(MOD(rand(), size));
uint8_t * buf = alloca(size);
/* make sure pad gets allocated above buf
* therefore moving "buf" on the stack at some random offset */
ASSERT(buf + 8192 <= pad);
/* fill the buffer (this should bring it into cache) */
for (int i = 0; i < size; i++)
{
buf[i] = i;
}
/* fill the buffer again; hoping some values won't reach the physical memory */
for (int i = 0; i < size; i++)
{
buf[i] = i + 1;
}
/* save it to card */
if (handle_cache & 1)
{
/* let the wrapper handle the cacheable buffer */
TEST_FUNC_CHECK(FIO_WriteFile(f, buf, size), == size);
}
else
{
/* Trick the wrapper into calling Canon stub directly,
* so it will no longer clean the cache before writing.
* This should fail - do not use it in practice.
* The uncacheable flag has no effect on DMA.
* You should either use fio_malloc (which returns uncacheable buffers)
* or pass regular (cacheable) pointers and let the wrapper handle them. */
TEST_FUNC_CHECK(FIO_WriteFile(f, UNCACHEABLE(buf), size), == size);
}
TEST_VOID(FIO_CloseFile(f));
/* reopen the file for reading */
TEST_FUNC_CHECK(f = FIO_OpenFile(test_file, O_RDONLY | O_SYNC), != 0);
/* read the file into uncacheable memory (this one will be read correctly) */
uint8_t * ubuf = fio_malloc(size);
TEST_FUNC_CHECK(ubuf, != 0);
if (!ubuf) goto cleanup;
TEST_FUNC_CHECK(FIO_ReadFile(f, ubuf, size), == size);
FIO_SeekSkipFile(f, 0, SEEK_SET);
/* alter the buffer contents; hoping some values will be only in cache */
for (int i = 0; i < size; i++)
{
buf[i] = i + 2;
}
/* read the file into regular (cacheable) memory */