 
     Display.display(2, 124, 1, refresh_lower ? 7 : 4);
   }
+
+  DUINO_WidgetContainer<2> * container_outer_;
+  DUINO_WidgetContainer<3> * container_top_;
+  DUINO_WidgetContainer<12> * container_notes_;
+  DUINO_DisplayWidget * widget_trigger_mode_;
+  DUINO_DisplayWidget * widget_key_;
+  DUINO_DisplayWidget * widget_scale_;
+  DUINO_DisplayWidget * widgets_notes_[12];
 
   bool trigger_mode;
   int8_t key;

    }
  }

 private:
  float note_cv(int octave, uint8_t key, uint8_t note)
  {
    return (float)octave + (float)key / 12.0 + (float)note / 12.0;
  }

  void get_note_indicator_coordinates(uint8_t note, uint16_t * x, uint16_t * y)
  {
    switch(note)
    {
      case 0: // C
        *x = 6;
        *y = 54;
        break;
      case 1: // Db
        *x = 15;
        *y = 29;
        break;
      case 2: // D
        *x = 24;
        *y = 54;
        break;
      case 3: // Eb
        *x = 33;
        *y = 29;
        break;
      case 4: // E
        *x = 42;
        *y = 54;
        break;
      case 5: // F
        *x = 60;
        *y = 54;
        break;
      case 6: // Gb
        *x = 69;
        *y = 29;
        break;
      case 7: // G
        *x = 78;
        *y = 54;
        break;
      case 8: // Ab
        *x = 87;
        *y = 29;
        break;
      case 9: // A
        *x = 96;
        *y = 54;
        break;
      case 10: // Bb
        *x = 105;
        *y = 29;
        break;
      case 11: // B
        *x = 114;
        *y = 54;
        break;
    }
  }

  void invert_current_selection()
  {
    if(main_selected)
    {
      int16_t x, y;
      get_note_indicator_coordinates(note_selected, &x, &y);
      Display.draw_pixel(x, y, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 2, y, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 4, y, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 6, y, DUINO_SH1106::Inverse);
      Display.draw_pixel(x, y + 2, DUINO_SH1106::Inverse);
      Display.draw_pixel(x, y + 4, DUINO_SH1106::Inverse);
      Display.draw_pixel(x, y + 6, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 2, y + 6, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 4, y + 6, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 6, y + 6, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 6, y + 2, DUINO_SH1106::Inverse);
      Display.draw_pixel(x + 6, y + 4, DUINO_SH1106::Inverse);
      if(y == 29)
      {
        Display.display(x, x + 6, 3, 4);
      }
      else
      {
        Display.display(x, x + 6, 6, 7);
      }
    }
    else
    {
      switch(top_selected)
      {
        case 0: // trigger mode
          Display.fill_rect(76, 0, 9, 9, DUINO_SH1106::Inverse);
          Display.display(76, 84, 0, 1);
          break;
        case 1: // key
          Display.fill_rect(90, 0, 13, 9, DUINO_SH1106::Inverse);
          Display.display(90, 102, 0, 1);
          break;
        case 2: // scale
          Display.fill_rect(108, 0, 19, 9, DUINO_SH1106::Inverse);
          Display.display(108, 126, 0, 1);
          break;
      }
    }
  }

  void display_trigger_mode()
  {
    bool selected = !main_selected && top_selected == 0;
    Display.fill_rect(77, 1, 7, 7, selected ? DUINO_SH1106::White : DUINO_SH1106::Black);

    Display.draw_bitmap_7(77, 1, icons, trigger_mode, selected ? DUINO_SH1106::Black : DUINO_SH1106::White);

    Display.display(77, 83, 0, 0);
  }

  void display_key()
  {
    bool selected = !main_selected && top_selected == 1;
    Display.fill_rect(91, 1, 11, 7, selected ? DUINO_SH1106::White : DUINO_SH1106::Black);

    bool sharp = false;
    unsigned char letter;

  {
    if(!trigger_mode || triggered)
    {
      if(scale == 0)
      {
        cv_out(CO1, 0.0);
        output_octave = 0;
        output_note = 0;
      }
      else
      {
        // read input
        float input = cv_read(CI1);

        // find a lower bound
        int below_octave = (int)input - 1;
        uint8_t below_note = 0;
        while(!(scale & (1 << below_note)))
        {
          below_note++;
        }

        // find closest lower and upper values
        int above_octave = below_octave, octave = below_octave;
        uint8_t above_note = below_note, note = below_note;
        while(note_cv(above_octave, key, above_note) < input)
        {
          note++;
          if(note > 11)
          {
            note = 0;
            octave++;
          }

          if(scale & (1 << note))
          {
            below_octave = above_octave;
            below_note = above_note;
            above_octave = octave;
            above_note = note;
          }
        }

        // output the nearer of the two values
        float below = note_cv(below_octave, key, below_note);
        float above = note_cv(above_octave, key, above_note);
        if(input - below < above - input)
        {
          cv_out(CO1, below);
          octave = below_octave;
          note = below_note;
        }
        else
        {
          cv_out(CO1, above);
          octave = above_octave;
          note = above_note;
        }

        // send trigger and update display note if note has changed
        if(octave != output_octave || note != output_note)
        {
          gt_out(GT1, true, true);
          output_octave = octave;
          output_note = note;
        }
      }
      
      // reset trigger
      triggered = false;
    }

    widget_loop();

    // display current note
    if(output_note != current_displayed_note)
