Norns - Need help with circular sequencer programming

Hey there,

first post! Nice to be here.

Let’s get down to it:
I am programming a circular sequencer for norns and need help with the drawing of the circular step “bars” (I have included the link to a picture to illustrate what I mean).

What already sort of works in the code below is drawing the dots in a circle that are used to select single steps. What I’ve been trying to do now is to have each note be represented by a step bar that starts halfway to the previous point selected by the step selector and ends halfway to the next (think like the outlines of a pie sliced into 16 pieces). The user is then supposed to be able to move the respective step bar up and down while it still adheres to the correct rotation in line with the circle.

I’ve been trying to crack this by making a grid with a finer resolution that the script can align the start and end points of the bars with (so like the for loop that fills in the step selector dots but with the number of radians quadrupled). However this kept tying knots into my brain and I lost track of what is what.

Can anyone help?

Cheers!

Design Reference:

Picture

Code
   function init()
          -- Initialize arrays & vars needed for circles 
          circle_x_vals = {}
          circle_y_vals = {}
          circle_radius = 0.75
      
   
      -- Fill in 16 points on the circle for selector dots
      for i=1, 16 do
        local c = 360 * (i / 16)           
        circle_x_vals[i] = math.floor((circle_radius * math.sin( math.rad(c)) *20) + 64)
        circle_y_vals[i] = math.floor((circle_radius * math.cos( math.rad(c)) *20) + 32)
      end
      
      selected_step = 1
      
      light_up_sel_step  = 9 -- Init var for brighter selected step
      bigger_sel_step = 1 -- Init var for bigger selected step
      
    end


    function redraw()
      screen.clear()
      screen.aa(0)
      
      --Draw step selector dots in a circle
      for i=1, 16 do
        sel_s = 1
        sel_l = 1
        if selected_step == i then 
          sel_l = sel_l + light_up_sel_step
          sel_s = sel_s + bigger_sel_step
        end
        
        screen.rect(circle_x_vals[i],circle_y_vals[i],sel_s,sel_s)
        
        -- Make step that is selected stand out
        screen.level(sel_l)
        screen.fill()
      end
      
      -- Draw step bars
      
        
      screen.update()
      
    end

    function enc (n,d)
      
      -- Make the 1st encoder move the step selection and handle 1&16
      if n == 2 then
       selected_step = selected_step + d
       if selected_step > 16 then
         selected_step = 1
       elseif selected_step < 1 then
         selected_step = 16
       end
       
      end
      
      if n == 3 then
        note_seq[selected_step] = note_seq[selected_step] + (d*0.1)
      end
      redraw()
      
      
    end
3 Likes

It draws a curve, not a straight line, but the screen:arc would be something i would react for to move forward with the design, and then maybe refactor later.

screen:arc (x, y, r, angle1, angle2)
1 Like

Erm so a sketch might be

function draw_step_bars()
  PI = 3.14159265359
  steps = 16
  screen.line_width(2)
  for i=1,steps do
      if i == selected_step then
        screen.level(15)
      else
        screen.level(1)
      end
      screen.arc(128/2, 64/2, 20, -(2*PI/steps)*i-0.1, -(2*PI/steps)*i+0.1)
      screen.stroke()
  end
end

The sketch uses steps which I imagine could be a global variable (yours is hardcoded to 16) but which is beyond your question, and also I have a feeling Lua might have π defined as a constant somewhere, maybe math.pi but I am not with my norns right now to verify.

1 Like

Hey there,

thank you so so much!! That solved my problem. Now they actually also have the shape I wanted (I had ditched that wish as I thought it would make things more complicated). I had already begun coding when you replied but thanks for sketching it out as well.

My code is very similar to yours:

    -- Draw step bars
  for i=1, 16 do
    local fwd = i+1
    
    if fwd > 16 then
      fwd = 1 
    end
    
    -- Draw 16 slices of the circle and offset by half a 16th to align step bars (Whole circle is 2*pi)
    screen.arc(64,32,note_seq[i]*15,((6.282/16)*i)+0.196,((6.282/16)*fwd)+0.196) 
    screen.level(15)
    screen.stroke()
  end
3 Likes

Sweet. Good luck design and coding and thanks also for the opportunity to do a bit of “before-breakfast” sketching in the morning :slight_smile:

1 Like

Thanks! And I’m glad that you got something out of it too :slight_smile:

1 Like