Advertisement
Guest User

500d Auido.c - Unified Magic Lantern

a guest
Nov 8th, 2011
566
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 26.76 KB
  1. /** \file
  2.  * Onscreen audio meters
  3.  */
  4. /*
  5.  * Copyright (C) 2009 Trammell Hudson <hudson+ml@osresearch.net>
  6.  *
  7.  * This program is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU General Public License
  9.  * as published by the Free Software Foundation; either version 2
  10.  * of the License, or (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the
  19.  * Free Software Foundation, Inc.,
  20.  * 51 Franklin Street, Fifth Floor,
  21.  * Boston, MA  02110-1301, USA.
  22.  */
  23. // include files
  24. #include "dryos.h"
  25. #include "bmp.h"
  26. #include "config.h"
  27. #include "property.h"
  28. #include "menu.h"
  29. #include "gui.h"
  30.  
  31.  
  32. // ML config variables - stored in magic.cfg on the card.
  33. CONFIG_INT( "audio.mgain",  mgain,      5 );
  34. CONFIG_INT( "audio.alc-enable", alc_enable, 0 );
  35. CONFIG_INT("audio.draw-meters", cfg_draw_meters, 2);
  36. CONFIG_INT( "audio.lovl",   lovl,       0 );
  37. CONFIG_INT("audio.monitoring", audio_monitoring, 1);
  38. CONFIG_INT( "audio.mic-power",  mic_power,  1 );
  39. int loopback = 1;
  40.  
  41. // Declare some stuff.
  42. static void audio_configure(int force);
  43. void sounddev_task();
  44. static int audio_cmd_to_gain_x1000(int cmd);
  45. static void audio_monitoring_display_headphones_connected_or_not();
  46. static void audio_menus_init();
  47. int do_draw_meters = 0;
  48. char label[10] = "RIGHT ";
  49. PROP_INT(PROP_USBRCA_MONITOR, rca_monitor);
  50.  
  51. // declare audio_thresholds here since it doesn't exist in the 500d ROM (thanks Alex).
  52. int audio_thresholds[] = { 0x7fff, 0x7213, 0x65ab, 0x5a9d, 0x50c2, 0x47fa, 0x4026, 0x392c, 0x32f4, 0x2d6a, 0x2879, 0x2412, 0x2026, 0x1ca7, 0x1989, 0x16c2, 0x1449, 0x1214, 0x101d, 0xe5c, 0xccc, 0xb68, 0xa2a, 0x90f, 0x813, 0x732, 0x66a, 0x5b7, 0x518, 0x48a, 0x40c, 0x39b, 0x337, 0x2dd, 0x28d, 0x246, 0x207, 0x1ce, 0x19c, 0x16f, 0x147 };
  53.  
  54. /****************************
  55.  *  Structure declerations
  56.  ****************************/
  57. struct gain_struct
  58. {
  59.     struct semaphore *  sem;
  60.     unsigned        alc1;
  61.     unsigned        sig1;
  62.     unsigned        sig2;
  63. };
  64.  
  65. static struct gain_struct gain = {
  66.     .sem            = (void*) 1,
  67. };
  68.  
  69. struct audio_level audio_levels[2];
  70.  
  71. struct audio_level *get_audio_levels(void)
  72. {
  73.     return audio_levels;
  74. }  
  75. /*--------------------------------*/
  76.  
  77.  
  78. /*****************************************************************************
  79.  * A function that isn't used, but I want to include it because it could be
  80.  * useful to someone else. Taken from original Audio.c file.
  81.  * -From Morgan Look
  82.  *****************************************************************************/
  83. void masked_audio_ic_write(
  84.                            unsigned reg,     // the register we wish to manipulate (eg AUDIO_IC_SIG1)
  85.                            unsigned mask, // the range of bits we want to manipulate (eg 0x05 or b0000111) to only allow changes to b3,b2,b0
  86.                            unsigned bits     // the bits we wish to set (eg 0x02 or b000010 to set b1, while clearing others within scope of the mask)
  87.                            )
  88. {
  89.     unsigned old;                       // variable to store current register value
  90.     old = audio_ic_read(reg);  // read current register value
  91.     old &= ~mask;                     // bitwise AND old value against inverted mask
  92.     bits &= mask;                      // limit scope of new bits with mask
  93.     _audio_ic_write(reg | bits | old);    // bitwise OR everything together and call _audio_ic_write function
  94. }
  95.  
  96. /*----------------------------------------------------------------------------*/
  97.  
  98. ///////////////////////////////////////////
  99. // Some functions that will be used later.
  100. ///////////////////////////////////////////
  101. int ext_cfg_draw_meters(void)
  102. {
  103.     return cfg_draw_meters;
  104. }
  105.  
  106. /** Returns a dB translated from the raw level
  107.  *
  108.  * Range is -40 to 0 dB
  109.  */
  110. static int
  111. audio_level_to_db(
  112.                   int           raw_level
  113.                   )
  114. {
  115.     int db;
  116.    
  117.     for( db = 40 ; db ; db-- )
  118.     {
  119.         if( audio_thresholds[db] > raw_level )
  120.             return -db;
  121.     }
  122.    
  123.     return 0;
  124. }
  125.  
  126. static uint8_t
  127. db_to_color(int db)
  128. {
  129.     if( db < -25 )
  130.         return 0x2F; // white
  131.     if( db < -12 )
  132.         return 0x06; // dark green
  133.     if( db < -3 )
  134.         return 0x0F; // yellow
  135.     return 0x0c; // dull red
  136. }
  137.  
  138. static uint8_t
  139. db_peak_to_color(int db)
  140. {
  141.     if( db < -25 )
  142.         return 11; // dark blue
  143.     if( db < -12 )
  144.         return 11; // dark blue
  145.     if( db < -3 )
  146.         return 15; // bright yellow
  147.     return 0x08; // bright red
  148. }
  149.  
  150. static void
  151. draw_meter(int x_origin, int y_origin, int meter_height, struct audio_level *level, char *label)
  152. {
  153.     const uint32_t width = 560; // bmp_width();
  154.     const uint32_t pitch = BMPPITCH;
  155.     uint32_t * row = (uint32_t*) bmp_vram();
  156.     if( !row )
  157.         return;
  158.    
  159.     // Skip to the desired y coord and over the
  160.     // space for the numerical levels
  161.     // .. and the space for showing the channel and source.
  162.     row += (pitch/4) * y_origin + AUDIO_METER_OFFSET + x_origin/4;
  163.    
  164.     const int db_peak_fast = audio_level_to_db( level->peak_fast );
  165.     const int db_peak = audio_level_to_db( level->peak );
  166.    
  167.     // levels go from -40 to 0, so -40 * 14 == 560 (=width)
  168.     const uint32_t x_db_peak_fast = (width + db_peak_fast * 14) / 4;
  169.     const uint32_t x_db_peak = (width + db_peak * 14) / 4;
  170.    
  171.     const uint8_t bar_color = db_to_color( db_peak_fast );
  172.     const uint8_t peak_color = db_peak_to_color( db_peak );
  173.    
  174.     const uint32_t bar_color_word = color_word( bar_color );
  175.     const uint32_t peak_color_word = color_word( peak_color );
  176.     const uint32_t bg_color_word = color_word(COLOR_BLACK);
  177.    
  178.     // Write the meter an entire scan line at a time
  179.     int y;
  180.     for( y=0 ; y<meter_height ; y++, row += pitch/4 )
  181.     {
  182.         uint32_t x;
  183.         for( x=0 ; x<width/4 ; x++ )
  184.         {
  185.             if( x < x_db_peak_fast )
  186.                 row[x] = bar_color_word;
  187.             else
  188.                 if( x < x_db_peak )
  189.                     row[x] = bg_color_word;
  190.                 else
  191.                     if( x < x_db_peak + 4 )
  192.                         row[x] = peak_color_word;
  193.                     else
  194.                         row[x] = bg_color_word;
  195.         }
  196.     }
  197.    
  198.     // Write the current level
  199.     bmp_printf( FONT(FONT_SMALL, COLOR_WHITE, COLOR_BLACK), x_origin, y_origin, "%s %02d", label, MIN(db_peak, -1) );
  200. }
  201.  
  202. static void
  203. draw_ticks(int x, int y, int tick_height)
  204. {
  205.     const uint32_t width = 560 + 8; // bmp_width();
  206.     const uint32_t pitch = BMPPITCH;
  207.     uint32_t * row = (uint32_t*) bmp_vram();
  208.     if( !row )
  209.         return;
  210.     row += (pitch/4) * y + AUDIO_METER_OFFSET - 2 + x/4;//seems to need less of an offset
  211.    
  212.     const uint32_t white_word = 0
  213.     | ( COLOR_WHITE << 24 )
  214.     | ( COLOR_WHITE << 16 )
  215.     | ( COLOR_WHITE <<  8 )
  216.     | ( COLOR_WHITE <<  0 );
  217.    
  218.     for( ; tick_height > 0 ; tick_height--, row += pitch/4 )
  219.     {
  220.         int db;
  221.         for( db=-40; db<= 0 ; db+=5 )
  222.         {
  223.             const uint32_t x_db = width + db * 14;
  224.             row[x_db/4] = white_word;
  225.         }
  226.     }
  227. }
  228.  
  229. /* Normal VU meter */
  230. static void draw_meters(void)
  231. {
  232.     int screen_layout = get_screen_layout();
  233.     // The db values are multiplied by 8 to make them
  234.     // smoother.
  235.     int erase = 0;
  236.     int hs = get_halfshutter_pressed();
  237.     static int prev_hs = 0;
  238.     if (hs != prev_hs) erase = 1;
  239.     prev_hs = hs;
  240.     int x0 = 0;
  241.     int y0 = 0;
  242.     int small = 0;
  243.    
  244.     if (gui_menu_shown())
  245.     {
  246.         x0 = os.x0 + os.x_ex/2 - 360;
  247.         y0 = os.y0 + os.y_ex/2 - 240;
  248.         y0 += 350;
  249.         x0 += 10;
  250.     }
  251.     else
  252.     {
  253.         small = hs;
  254.         x0 = os.x0 + os.x_ex/2 - 360;
  255.         if (screen_layout == SCREENLAYOUT_3_2) y0 = os.y0; // just above the 16:9 frame
  256.         else if (screen_layout == SCREENLAYOUT_16_9) { small = 1; y0 = os.y0 + os.off_169; } // meters just below 16:9 border
  257.         else if (screen_layout == SCREENLAYOUT_16_10) {small = 1; y0 = os.y0 + os.off_1610; } // meters just below 16:10 border
  258.         else if (screen_layout == SCREENLAYOUT_UNDER_3_2) y0 = MIN(os.y_max, vram_bm.height - 54);
  259.         else if (screen_layout == SCREENLAYOUT_UNDER_16_9) y0 = MIN(os.y_max - os.off_169, vram_bm.height - 54);
  260.         if (hdmi_code) small = 1;
  261.     }
  262.    
  263.     if (erase)
  264.     {
  265.         bmp_fill(
  266.                  screen_layout >= SCREENLAYOUT_UNDER_3_2 ? BOTTOMBAR_BGCOLOR : TOPBAR_BGCOLOR,
  267.                  x0, y0, 720, small ? 20 : 34
  268.                  );
  269.     }
  270.     else if (hs) return; // will draw top bar instead
  271.     else if (!small)
  272.     {
  273.         // mono mic on 500d :(
  274.         draw_ticks( x0, y0 + 10, 3 );
  275.         draw_meter( x0, y0 + 12, 10, &audio_levels[0], label);
  276.         draw_ticks( x0, y0 + 20, 3 );
  277.     }
  278.     else
  279.     {
  280.         draw_ticks( x0, y0 + 7, 2 );
  281.         draw_meter( x0, y0 + 8, 7, &audio_levels[0], label);
  282.         draw_ticks( x0, y0 + 17, 2 );
  283.     }
  284.     if (gui_menu_shown() && alc_enable)
  285.     {
  286.         int dgain_x1000 = audio_cmd_to_gain_x1000(audio_ic_read(AUDIO_IC_ALCVOL));
  287.         bmp_printf(FONT_MED, 10, 340, "AGC:%s%d.%03d dB", dgain_x1000 < 0 ? "-" : " ", ABS(dgain_x1000) / 1000, ABS(dgain_x1000) % 1000);
  288.     }
  289. }
  290.  
  291. static void
  292. compute_audio_levels(int ch)
  293. {
  294.     struct audio_level * const level = &audio_levels[ch];
  295.    
  296.     int raw = audio_read_level( ch );
  297.     if( raw < 0 )
  298.         raw = -raw;
  299.    
  300.     level->last = raw;
  301.     level->avg  = (level->avg * 15 + raw) / 16;
  302.     if( raw > level->peak )
  303.         level->peak = raw;
  304.    
  305.     if( raw > level->peak_fast )
  306.         level->peak_fast = raw;
  307.    
  308.     // Decay the peak to the average
  309.     level->peak = ( level->peak * 63 + level->avg ) / 64;
  310.     level->peak_fast = ( level->peak_fast * 7 + level->avg ) / 8;
  311. }
  312.  
  313. void audio_monitoring_display_headphones_connected_or_not()
  314. {
  315.     NotifyBoxHide();
  316.     NotifyBox(2000,
  317.               "Headphones %s",
  318.               AUDIO_MONITORING_HEADPHONES_CONNECTED ?
  319.               "connected" :
  320.               "disconnected");
  321. }
  322.  
  323. static void audio_monitoring_force_display(int x)
  324. {
  325.     prop_deliver(*(int*)(HOTPLUG_VIDEO_OUT_PROP_DELIVER_ADDR), &x, 4, 0x0);
  326. }
  327.  
  328. static void audio_monitoring_update()
  329. {
  330.     // kill video connect/disconnect event... or not
  331.     *(int*)HOTPLUG_VIDEO_OUT_STATUS_ADDR = audio_monitoring ? 2 : 0;
  332.    
  333.     if (audio_monitoring && rca_monitor)
  334.     {
  335.         audio_monitoring_force_display(0);
  336.         msleep(1000);
  337.         audio_monitoring_display_headphones_connected_or_not();
  338.     }
  339. }
  340.  
  341. int audio_meters_are_drawn()
  342. {
  343.     return
  344.     (
  345.      is_movie_mode() && cfg_draw_meters && do_draw_meters && get_global_draw() && !gui_menu_shown() && lv_dispsize == 1
  346.      )
  347.     ||
  348.     (
  349.      gui_menu_shown() && is_menu_active("Audio") && cfg_draw_meters
  350.      );
  351. }
  352.  
  353. static inline unsigned mgain_index2gain(int index) // sorted mgain values
  354. {
  355.     static uint8_t gains[] = { 0, 3, 6, 10, 17, 20, 23, 26, 29, 32 };
  356.     return gains[COERCE(index, 0, 10)];
  357. }
  358.  
  359. static int
  360. audio_cmd_to_gain_x1000(
  361.                         int         cmd
  362.                         )
  363. {
  364.     int gain_x1000 = (cmd - 145) * 375;
  365.     return gain_x1000;
  366. }
  367.  
  368. static void
  369. enable_meters(int mode)
  370. {
  371.     loopback = do_draw_meters = !mode;
  372.     audio_configure( 1 );
  373. }
  374.  
  375. /*-------------------------------------------*/
  376.  
  377.  
  378. /******************************
  379.  *  Dummy functions for now.
  380.  ******************************/
  381. void volume_up()
  382. {
  383.  
  384. }
  385.  
  386. void volume_down()
  387. {
  388.  
  389. }
  390. /*--------------------------------*/
  391.  
  392.  
  393. /**************************************
  394.  *   Property stuff goes here.
  395.  **************************************/
  396.  
  397. PROP_HANDLER( PROP_LV_ACTION )
  398. {
  399.     const unsigned mode = buf[0];
  400.     enable_meters( mode );
  401.     return prop_cleanup( token, property );
  402. }
  403. /*---------------------------------------*/
  404.  
  405.  
  406. /*********************************************************************
  407.  *              Analog gain control function.
  408.  *
  409.  *      This is messy I know, but it's the only way I know how to do it.
  410.  *      The problem is that the 500d has to change 3 bits in AUDIO_IC_SIG1,
  411.  *      but the other cameras only have to change 2, so I can't use Trammell's
  412.  *      routine here, I had to write my own. Also, this way we get to use all
  413.  *      of the extra gain settings the 500d has :).
  414.  *
  415.  *      This basically writes the required bits one at a time (in seperate statements),
  416.  *      which is easier to read and understand, but probably not very efficient.
  417.  *
  418.  *      I used the PDF on the AK4346 audio chip from here:
  419.  *      http://www.asahi-kasei.co.jp/akm/en/product/ak4636/ak4636_f01e.pdf
  420.  *
  421.  *      -Coutts
  422.  *********************************************************************/
  423. static inline void
  424. audio_ic_set_mgain(
  425.                    unsigned     mgain
  426.                    )
  427. {
  428.     unsigned sig1 = audio_ic_read( AUDIO_IC_SIG1 ); // Read the value of register 'Signal Select 1', store it in sig1.
  429.                                                     // We will use this later when we set individual bits on/off for
  430.                                                     // different gain values.
  431.     unsigned sig2 = audio_ic_read( AUDIO_IC_SIG2 ); // Read the value of register 'Signal Select 2', store it in sig2.
  432.    
  433.    
  434.     // Setting the bits for each possible gain setting in the 500d, individually so it's easy to understand.
  435.     //      - 24 hours ago I didn't even understand how to configure the audio chip, so I think this is pretty good
  436.     //        for my first implemenation :)
  437.     //
  438.     // Basically, different gain settings use different combinations of the MGAIN0, MGAIN1, MGAIN2, and MGAIN3 bits being set/cleared.
  439.     // Here's a reference table for the settings, taken from the pdf linked from line 201 above:
  440.     //
  441.     //---------------------------------------------------------
  442.     // MGAIN3  |  MGAIN2  |  MGAIN1  |  MGAIN0 ||  Gain Value
  443.     //---------------------------------------------------------
  444.     //    0    |     0    |    0     |    0    ||     0 dB
  445.     //    0    |     0    |    0     |    1    ||   +20 dB (default setting)
  446.     //    0    |     0    |    1     |    0    ||   +26 dB
  447.     //    0    |     0    |    1     |    1    ||   +32 dB
  448.     //    0    |     1    |    0     |    0    ||   +10 dB
  449.     //    0    |     1    |    0     |    1    ||   +17 dB
  450.     //    0    |     1    |    1     |    0    ||   +23 dB
  451.     //    0    |     1    |    1     |    1    ||   +29 dB
  452.     //    1    |     0    |    0     |    0    ||    +3 dB
  453.     //    1    |     0    |    0     |    1    ||    +6 dB
  454.     //---------------------------------------------------------
  455.     //
  456.     // So my switch statement below looks at the value of the mgain variable (which is changed by the gain setting in the ML menu),
  457.     // and sets the correct combination of bits accordingly.
  458.     //
  459.     // &= ~(1 << x) means clear bit x
  460.     // |= 1 << x means set bit x
  461.     //
  462.     // That should be enough to bring anybody up to speed on things.
  463.     // -Coutts
  464.     switch (mgain)
  465.     {
  466.         case 0: // 0 dB
  467.             sig1 &= ~(1 << 0); //clear bit1 [MGAIN0] in register 'Signal Select 1'
  468.             sig1 &= ~(1 << 1); //clear bit2 [MGAIN2]    "
  469.             sig1 &= ~(1 << 3); //clear bit3 [MGAIN3]    "
  470.             sig2 &= ~(1 << 5); //clear bit4 [MGAIN1] in register 'Signal Select 2'
  471.             break;
  472.            
  473.         case 1: // 3 dB
  474.             sig1 &= ~(1 << 0); //clear MGAIN0
  475.             sig1 &= ~(1 << 1); //clear MGAIN2
  476.             sig1 |= 1 << 3;    //set MGAIN3
  477.             sig2 &= ~(1 << 5); //clear MGAIN1
  478.             break;
  479.            
  480.         case 2: // 6 dB
  481.             sig1 &= ~(1 << 1);  //  [etc, etc, etc]
  482.             sig1 |= 1 << 0;     //    |         |
  483.             sig1 |= 1 << 3;     //    |         |
  484.             sig2 &= ~(1 << 5);  //    V         V
  485.             break;
  486.            
  487.         case 3: // 10 dB
  488.             sig1 &= ~(1 << 0);
  489.             sig1 &= ~(1 << 3);
  490.             sig1 |= 1 << 1;
  491.             sig2 &= ~(1 << 5);
  492.             break;
  493.            
  494.         case 4: // 17 dB
  495.             sig1 &= ~(1 << 3);
  496.             sig1 |= 1 << 0;
  497.             sig1 |= 1 << 1;
  498.             sig2 &= ~(1 << 5);
  499.             break;
  500.            
  501.         case 5: // 20 dB
  502.             sig1 &= ~(1 << 1);
  503.             sig1 &= ~(1 << 3);
  504.             sig1 |= 1 << 0;            
  505.             sig2 &= ~(1 << 5);
  506.             break;
  507.            
  508.         case 6: // 23 dB
  509.             sig1 &= ~(1 << 0);
  510.             sig1 &= ~(1 << 3);
  511.             sig1 |= 1 << 1;
  512.             sig2 |= 1 << 5;
  513.             break;
  514.            
  515.         case 7: // 26 dB
  516.             sig1 &= ~(1 << 0);
  517.             sig1 &= ~(1 << 1);
  518.             sig1 &= ~(1 << 3);
  519.             sig2 |= 1 << 5;
  520.             break;
  521.            
  522.         case 8: // 29 dB
  523.             sig1 &= ~(1 << 3);
  524.             sig1 |= 1 << 0;
  525.             sig1 |= 1 << 1;
  526.             sig2 |= 1 << 5;
  527.             break;
  528.            
  529.         case 9: // 32 dB
  530.             sig1 &= ~(1 << 1);
  531.             sig1 &= ~(1 << 3);
  532.             sig1 |= 1 << 0;
  533.             sig2 |= 1 << 5;
  534.             break;
  535.     }
  536.    
  537.     audio_ic_write( AUDIO_IC_SIG1 | sig1 ); // Now that the correct bits in sig1 and sig2 have been set/cleared for whatever
  538.     gain.sig1 = sig1;                                       // gain setting we want, now it's time to write our new values for 'Signal Select 1'
  539.                                             // and 'Signal Select 2' to their respective registers in the audio chip.
  540.     audio_ic_write( AUDIO_IC_SIG2 | sig2 );
  541.     gain.sig2 = sig2;
  542. }
  543. /*-------------------------------------------------------*/
  544.  
  545.  
  546. /************************************************************************
  547.  *      Reconfigure the audio chip registers to toggle things like AGC.
  548.  ************************************************************************/
  549. static void
  550. audio_configure( int force )
  551. {
  552.     // No need to worry about input source, we only have one option on the 500d.
  553.     snprintf(label,  sizeof(label),  " INT ");
  554.    
  555.     bmp_printf(FONT_MED, 0, 200, "gain.alc: %x", gain.alc1);
  556.     bmp_printf(FONT_MED, 0, 220, "gain.sig1: %x", gain.sig1);
  557.     bmp_printf(FONT_MED, 0, 240, "gain.sig2: %x", gain.sig2);
  558.    
  559.     if( !force )
  560.     {
  561.         //////////////////////////////////////////////////////////////////////////
  562.         // Check if AGC or analog gain settings have changed, if they are still
  563.         // the same, then don't do anything - no need to set things that are
  564.         // already set :)
  565.         // -Coutts
  566.         //////////////////////////////////////////////////////////////////////////
  567.         if( audio_ic_read( AUDIO_IC_ALC1 ) == gain.alc1
  568.            &&  audio_ic_read( AUDIO_IC_SIG1 ) == gain.sig1
  569.            &&  audio_ic_read( AUDIO_IC_SIG2 ) == gain.sig2
  570.            )
  571.             return;
  572.     }
  573.    
  574.     ///////////////////////////////////////////////////////////////////
  575.     // Power up some modules used for line out and stuff - not sure
  576.     // about much behind this, but this register seems to be identical
  577.     // between the AK4346 and AK4646 chips, so I guess it's okay.
  578.     // -Coutts
  579.     ///////////////////////////////////////////////////////////////////
  580.     //audio_ic_write( AUDIO_IC_PM1 | 0x6D );
  581.     /*------------------------------------------------------------------*/
  582.    
  583.     audio_ic_write( AUDIO_IC_SIG1 | 0x14 ); // enables headphone loopback in play mode.
  584.    
  585.     ////////////////////////////////////////////////////////////////////////////////////
  586.     ////////////// Set the bits in 'Signal Select 2' for line out *only* ///////////////
  587.     ////////////////////////////////////////////////////////////////////////////////////
  588.     // Only set the third bit, in binary it's '100', this is just to set the BEEPA bit.
  589.     //
  590.     // In the AK4646 chip it's called BEEPL, but they appear to be the same thing.
  591.     // The purpose of this is to switch the BEEP signal to the mono-amp, which I guess
  592.     // means mono line out?
  593.     //
  594.     // Also, we don't need to set bits 1 and 2 like in the AK4646 chip. These bits are for
  595.     // LOVL0 and LOVL1, which control stereo line out gain, with either +0db, +2db, +4db, or +6db.
  596.     //
  597.     // The 500d only uses one bit for this, which means we only have 2 options. +0db or +3db.
  598.     // Our bit is located in register 'Signal Select 4'. In the AK4646 chip, the register in this location
  599.     // is 'Power Management 3'. This register is named simply 'LOVL'.
  600.     //
  601.     // So, instead of setting bits 1 and 2 in AUDIO_IC_SIG2, we actually need to set bit 7 in 'Signal Select 4'.
  602.     //
  603.     // -Coutts
  604.     ////////////////////////////////////////////////////////////////////////////////////
  605.     audio_ic_write( AUDIO_IC_SIG2 | 0x4 ); // 0x4 == 00000100.
  606.    
  607.     // Set the mono line gain to +3db (max).
  608.     audio_ic_write( AUDIO_IC_SIG4 | 0x40 ); // 0x40 == 01000000.
  609.     /*-----------------------------------*/
  610.    
  611.    
  612.     gain.alc1 = alc_enable ? (1<<5) : 0;
  613.     audio_ic_write( AUDIO_IC_ALC1 | gain.alc1 ); // disable all ALC
  614.    
  615.     // Update the analog gain settings.
  616.     audio_ic_set_mgain( mgain );
  617. }
  618. /*------------------------------------------------------------------------*/
  619.  
  620.  
  621. /**********************************************
  622.  *      Toggling functions for menu settings.  
  623.  **********************************************/
  624. static void
  625. audio_mgain_toggle( void * priv ) //toggle forward for analog gain.
  626. {
  627.     unsigned * ptr = priv;
  628.     *ptr = mod((*ptr + 1), 10);
  629.     audio_configure( 1 );
  630. }
  631.  
  632. static void
  633. audio_mgain_toggle_reverse( void * priv ) //toggle reverse for analog gain.
  634. {
  635.     unsigned * ptr = priv;
  636.     *ptr = mod((*ptr - 1), 10);
  637.     audio_configure( 1 );
  638. }
  639.  
  640. static void
  641. audio_monitoring_toggle( void * priv)
  642. {
  643.     audio_monitoring = !audio_monitoring;
  644.     audio_monitoring_update();
  645. }
  646. /*----------------------------------------*/
  647.  
  648.  
  649. /******************************************
  650.  *      Display functions for menus.   
  651.  ******************************************/
  652. static void
  653. audio_alc_display( void * priv, int x, int y, int selected )
  654. {
  655.     unsigned fnt = selected ? MENU_FONT_SEL : MENU_FONT;
  656.     bmp_printf(
  657.                FONT(fnt, alc_enable ? COLOR_RED : FONT_FG(fnt), FONT_BG(fnt)),
  658.                x, y,
  659.                "AGC           : %s",
  660.                alc_enable ? "ON " : "OFF"
  661.                );
  662. }
  663.  
  664. static void
  665. audio_mgain_display( void * priv, int x, int y, int selected )
  666. {
  667.     bmp_printf(
  668.                selected ? MENU_FONT_SEL : MENU_FONT,
  669.                x, y,
  670.                "Analog Gain   : %d dB",
  671.                mgain_index2gain(mgain)
  672.                );
  673.     menu_draw_icon(x, y, MNI_PERCENT, mgain_index2gain(mgain) * 100 / 32);
  674. }
  675.  
  676. static void
  677. audio_meter_display( void * priv, int x, int y, int selected )
  678. {
  679.     unsigned v = *(unsigned*) priv;
  680.     bmp_printf(
  681.                selected ? MENU_FONT_SEL : MENU_FONT,
  682.                x, y,
  683.                "Audio Meters  : %s",
  684.                v ? "ON" : "OFF"
  685.                );
  686.     menu_draw_icon(x, y, MNI_BOOL_GDR(v));
  687. }
  688.  
  689. static void
  690. audio_monitoring_display( void * priv, int x, int y, int selected )
  691. {
  692.     bmp_printf(
  693.                selected ? MENU_FONT_SEL : MENU_FONT,
  694.                x, y,
  695.                "Monitoring-USB: %s",
  696.                audio_monitoring ? "ON" : "OFF"
  697.                );
  698. }
  699. /*----------------------------------------*/
  700.  
  701.  
  702. /******************************************
  703.  *      Audio menu order / layout  
  704.  ******************************************/
  705. static struct menu_entry audio_menus[] = {
  706.     {
  707.         .name = "Audio Meters",
  708.         .priv       = &cfg_draw_meters,
  709.         .select     = menu_binary_toggle,
  710.         .display    = audio_meter_display,
  711.         .help = "Bar peak decay, from -40 dB to 0 dB, yellow at -12dB."
  712.     },
  713.     {
  714.         .name = "AGC",
  715.         .priv       = &alc_enable,
  716.         .select     = menu_binary_toggle,
  717.         .display    = audio_alc_display,
  718.         .help = "Automatic Gain Control - turn it off :)"
  719.     },
  720.     {
  721.         .name = "Analog Gain (dB)",
  722.         .priv       = &mgain,
  723.         .select     = audio_mgain_toggle,
  724.         .select_reverse = audio_mgain_toggle_reverse,
  725.         .display    = audio_mgain_display,
  726.         .help = "Gain applied to both inputs in analog domain (preferred)."
  727.     },
  728.     {
  729.         .name = "Monitoring-USB",
  730.         .priv = &audio_monitoring,
  731.         .select     = audio_monitoring_toggle,
  732.         .display    = audio_monitoring_display,
  733.         .help = "Audio monitoring via USB. Disable if you use a SD display."
  734.     },
  735. };
  736. /*----------------------------------------*/
  737.  
  738.  
  739. /******************************************
  740.  *      Display the Audio menu section.
  741.  ******************************************/
  742. static void audio_menus_init()
  743. {
  744.     menu_add( "Audio", audio_menus, COUNT(audio_menus) );
  745. }
  746. /*----------------------------------------*/
  747.  
  748.  
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756.     /*********************************************************
  757.      *--------------------------------------------------------
  758.      *                  ALL TASKS AFTER THIS
  759.      *--------------------------------------------------------
  760.      *********************************************************/
  761.  
  762.  
  763.  
  764.  
  765. /******************************************************************************
  766.  *      Our version of canon's sounddev task. We override canon's task
  767.  *      so that we can change things like AGC and analog/digital gain.
  768.  *
  769.  *      If this is a magic_off boot, then just call canon's built-in
  770.  *      task and don't do anything.
  771.  ******************************************************************************/
  772. static void
  773. my_sounddev_task()
  774. {
  775.     msleep( 2000 );
  776.    
  777.     // If this is a magic_off boot, don't start our task, just call canon's task.
  778.     if (magic_is_off()) { sounddev_task(); return; }
  779.    
  780.     // Wait until ML has started up.
  781.     hold_your_horses(1);
  782.    
  783.     // Semaphores
  784.     gain.sem = create_named_semaphore( "audio_gain", 1);
  785.     sounddev.sem_alc = CreateBinarySemaphore( 0, 0 );
  786.    
  787.     audio_configure( 1 ); // force it to run this first time to re-configure the sound device.
  788.     msleep(500);
  789.     audio_monitoring_update(); // Update audio monitoring stuff.
  790.    
  791.     while(1) //time to loop!!
  792.     {
  793.         int rc = take_semaphore( gain.sem, 1000 );
  794.         if(gui_state != GUISTATE_PLAYMENU || (audio_monitoring && AUDIO_MONITORING_HEADPHONES_CONNECTED)) {
  795.             audio_configure( rc == 0 ); // force it if we got the semaphore
  796.         }
  797.     }
  798. }
  799. // override canon's sounddev task with our own.
  800. TASK_OVERRIDE( sounddev_task, my_sounddev_task );
  801. /*--------------------------------------------------------------------------------*/
  802.  
  803.  
  804. /******************************************************************************
  805.  * Task to monitor the audio levels.
  806.  *
  807.  * Compute the average and peak level, periodically calling
  808.  * the draw_meters() function to display the results on screen.
  809.  * \todo Check that we have live-view enabled and the TFT is on
  810.  * before drawing.
  811.  ******************************************************************************/
  812. static void
  813. meter_task( void* unused )
  814. {
  815.     audio_menus_init();
  816.    
  817.     while(1)
  818.     {
  819.         msleep( 50 );
  820.        
  821.         if (is_menu_help_active()) continue;
  822.        
  823.         if (audio_meters_are_drawn())
  824.         {
  825.             if (!is_mvr_buffer_almost_full())
  826.                 BMP_LOCK( draw_meters(); )
  827.                 }
  828.        
  829.         if (audio_monitoring)
  830.          {
  831.          static int hp = 0;
  832.          int h = AUDIO_MONITORING_HEADPHONES_CONNECTED;
  833.          
  834.          if (h != hp)
  835.          {
  836.          audio_monitoring_display_headphones_connected_or_not();
  837.          }
  838.          hp = h;
  839.          }
  840.     }
  841. }
  842. /*------------------------------------------------------------*/
  843.  
  844. TASK_CREATE( "meter_task", meter_task, 0, 0x18, 0x1000 );
  845.  
  846.  
  847. /****************************************************
  848.  * Monitor the audio levels very quickly
  849.  ****************************************************/
  850. static void
  851. compute_audio_level_task( void* unused )
  852. {
  853.     audio_levels[0].peak = audio_levels[1].peak = 0;
  854.     audio_levels[0].avg = audio_levels[1].avg = 0;
  855.    
  856.     while(1)
  857.     {
  858.         msleep( 10 );
  859.         compute_audio_levels( 0 );
  860.         compute_audio_levels( 1 );
  861.     }
  862. }
  863.  
  864. TASK_CREATE( "audio_level_task", compute_audio_level_task, 0, 0x18, 0x1000 );
  865.  
  866.  
Advertisement
RAW Paste Data Copied
Advertisement