electro-music.com   Dedicated to experimental electro-acoustic
and electronic music
 
    Front Page  |  Articles  |  Radio
 |  Media  |  Forum  |  Wiki  |  Links  |  Store
Forum with support of Syndicator RSS
 FAQFAQ   CalendarCalendar   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   LinksLinks
 RegisterRegister   ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in  Chat RoomChat Room 
Live streaming at radio.electro-music.com

  host / artist show at your time
  Antimon Antimon Waves

poster

Please visit the chat
 Forum index » DIY Hardware and Software » Lunettas - circuits inspired by Stanley Lunetta
CMUSE
Post new topic   Reply to topic Moderators: mosc
Page 1 of 1 [3 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
Author Message
PHOBoS



Joined: Jan 14, 2010
Posts: 3570
Location: Moon Base
Audio files: 539

PostPosted: Sat Sep 23, 2017 6:48 am    Post subject: CMUSE
Subject description: CMOS Triadex Muse (not tested)
Reply with quote  Mark this post and the followings unread

a few weeks ago AlanP posted this link to a javascript version of the Triadex Muse in the chatroom.
I immediatley thought that it wouldn't be too hard to recreate with a handfull of CMOS chips and
after a couple of days I couldn't resist the urge any longer and started drawing up a schematic.

I made use of this blockdiagram, the user manual and the programming manual. I also tested this
windows version. To get the timing correct I actually watched some demo videos frame by frame as
both the javascript and windows versions aren't 100% true to the actual muse. But I've also noticed
that there seemed to be a difference between muses (they also have different colored lights).

On to the circuit..
The original muse has 1 switch for both auto and step mode. you could actually use a toggle switch that
returns to it's center position from one side but they can be a bit harder to come by so I added a seperate
step button instead. I didn't add a debouce circuit so if you would use it as it is it'll probably be all over the
place. I also used a seperate reset switch (an external signal could be used as well) and if you add the
inverter and diode it will also stop the oscillator. The C 1/2 output is inverted which I found out after watching
some videos. C1, C2, C4, C8 are just divisions of the CLK frequency. For the odd divisions C3, C6 an XOR
gate is used and it is based on the examples found here.

The other part of the control circuit is a large shifregister made by chaining a couple smaller ones. The data
input bit is selected with switches W, X, Y Z which are connected to a parity generator made with 3 XOR gates.
If there is an even number of 1's selected with the switches the output will be 0 if there is an odd number of
1's it will be 1. (I think this was incorrect in either the javascript or windows version). This combination of
shiftregisters and XOR gates actually foms a LFSR which could create some pretty long sequences.

In the original muse the outputs from switches A, B, C, D are connected to a DAC which is used to control a
VCO. Getting the tuning right could be rather tricky so I went for a different, full CMOS, method instead which
is starting with a very high frequency and dividing it down to get the correct notes. The same way I made the
Chromatic Melody Generator. Switch D is used to select the octave (0 = one octave lower) which is done with U10b.

One thing that I haven't fully figured out yet is how the rest switch on the Muse functions. In the manual it says
it replaces the lowest note with a pause but I am not sure if the lowest note is just the low C or the output of
switch A or actually the lowest note in the sequence. Although I think that would be rather hard to implement.
I guess I could check the javascript and windows versions to see what they do.


I am not intending to actually built it although it is tempting. But besides the long shiftregister I pretty much have
all the components already in my current lunetta system so I could patch up something similar. If you do plan on
making one you'll probably won't be able to get 40 position slide switches and I think the best substitute would be
2x40 pin headers in combination with jumpers. Of course you could also adjust the number of dividers and shift-
registers. I was actually thinking about making a mini-cmuse.


CMUSE.gif
 Description:
 Filesize:  166.94 KB
 Viewed:  90 Time(s)
This image has been reduced to fit the page. Click on it to enlarge.

CMUSE.gif



_________________
"My perf, it's full of holes!"
http://phobos.000space.com/
SoundCloud BandCamp AcidTrasH Stickney Synthyards

Last edited by PHOBoS on Sat Sep 23, 2017 11:19 am; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger
Blue Hell
Site Admin


Joined: Apr 03, 2004
Posts: 22315
Location: The Netherlands, Enschede
Audio files: 212
G2 patch files: 319

PostPosted: Sat Sep 23, 2017 7:30 am    Post subject: Reply with quote  Mark this post and the followings unread

Cool

Great you figured it all out PHOBoS! This one I do understand at least.

_________________
Jan
Back to top
View user's profile Send private message Visit poster's website
Blue Hell
Site Admin


Joined: Apr 03, 2004
Posts: 22315
Location: The Netherlands, Enschede
Audio files: 212
G2 patch files: 319

PostPosted: Sun Sep 24, 2017 7:59 am    Post subject: Reply with quote  Mark this post and the followings unread

Re. the parity generator, odd parity seems more interesting than even parity, I've added an inversion for that after the xors.

Otherwise:

When the W, X, Y, Z switches are all switched to a position beyond the divider signals, and the shift register holds all zeros the xor yields a zero too - meaning the shifter state never changes.

Maybe this is the case for the original .. but I've found things to be a bit more interesting with the inverter added.

Now I need to figure out a good way to generate an output signal - I've implemented the thing as a controller, that is, it has no oscillator of it's own but just the weighted outputs of switch_a .. d summed (a DAC, say, or an R2R ladder).

Current code:

[Edit : spot the bugs :-)

I've changed things a bit since ... fixed the bugs, added a fifth interval selector, added div 5 and div 7 and added two external inputs going to the switches - so the switches now have 44 positions. Also added modulation inputs to each switch, decided to just keep the DA converter, that' s why I added switch E, to have 32 distinct output values, which seems plenty (using it with an external quantizer to make the actual note values)]

Code:
interface


  TModAmuse = class( TMod)
  strict private
  const
    i_reset =  0;
    i_trig  =  1;
    i_sela  =  2;
    i_selb  =  3;
    i_selc  =  4;
    i_seld  =  5;
    i_selw  =  6;
    i_selx  =  7;
    i_sely  =  8;
    i_selz  =  9;
  const
    o_out   =  0;
  private
    FOldRes    : Boolean;
    FOldTrig   : Boolean;
    FCountC1   : Integer;
    FCountC2   : Integer;
    FCountC3   : Integer;
    FCountC4   : Integer;
    FCountC6   : Integer;
    FCountC8   : Integer;
    FShifter   : Cardinal;
    FMemoryC1  : Boolean;
    FMemoryC2  : Boolean;
    FMemoryC3  : Boolean;
    FMemoryC4  : Boolean;
    FMemoryC6  : Boolean;
    FMemoryC8  : Boolean;
  public
    procedure   CreateIO;      override;
    procedure   DoSlowTick;    override;
  end;



implementation


  function  SignalToLogic( const aValue: TSignal): Boolean; inline;
  begin
    Result := aValue > 0;
  end;


  function DecToZeroWithResetValue( var aValue: Integer; aResetValue: Integer): Boolean; inline;
  begin
    Result := False;

    if aValue > 1
    then Dec( aValue)
    else begin
      aValue := aResetValue;
      Result := True;
    end;
  end;


  function  DecToZeroWithResetValueToggle( var aValue : Integer; var Memory: Boolean; aResetValue: Integer): Boolean; inline;
  begin
    if DecToZeroWithResetValue( aValue, aResetValue)
    then Memory := not Memory;

    Result := Memory;
  end;




{ ========
  TModAmuse = class( TMod)
}

    procedure   TModAmuse.CreateIO; // override;
    begin
      FIsSlow := True;
      AddInput ( i_reset, 'reset');
      AddInput ( i_trig , 'trig');
      AddInput ( i_sela , 'sela');
      AddInput ( i_selb , 'selb');
      AddInput ( i_selc , 'selc');
      AddInput ( i_seld , 'seld');
      AddInput ( i_selw , 'selw');
      AddInput ( i_selx , 'selx');
      AddInput ( i_sely , 'sely');
      AddInput ( i_selz , 'selz');
      AddOutput( o_out  , 'out' );
    end;


    procedure   TModAmuse.DoSlowTick; // override;

      function Select( aPos: Integer): Boolean;
      begin
        case aPos of
           1 : Result := True;
           2 : Result := FOldTrig;
           3 : Result := FMemoryC1;
           4 : Result := FMemoryC2;
           5 : Result := FMemoryC4;
           6 : Result := FMemoryC8;
           7 : Result := FMemoryC3;
           8 : Result := FMemoryC6;
           9 : Result := ( FShifter and ( 1 shl  0)) <> 0;
          10 : Result := ( FShifter and ( 1 shl  1)) <> 0;
          11 : Result := ( FShifter and ( 1 shl  2)) <> 0;
          12 : Result := ( FShifter and ( 1 shl  3)) <> 0;
          13 : Result := ( FShifter and ( 1 shl  4)) <> 0;
          14 : Result := ( FShifter and ( 1 shl  5)) <> 0;
          15 : Result := ( FShifter and ( 1 shl  6)) <> 0;
          16 : Result := ( FShifter and ( 1 shl  7)) <> 0;
          17 : Result := ( FShifter and ( 1 shl  8)) <> 0;
          18 : Result := ( FShifter and ( 1 shl  9)) <> 0;
          19 : Result := ( FShifter and ( 1 shl 10)) <> 0;
          20 : Result := ( FShifter and ( 1 shl 11)) <> 0;
          21 : Result := ( FShifter and ( 1 shl 12)) <> 0;
          22 : Result := ( FShifter and ( 1 shl 13)) <> 0;
          23 : Result := ( FShifter and ( 1 shl 14)) <> 0;
          24 : Result := ( FShifter and ( 1 shl 15)) <> 0;
          25 : Result := ( FShifter and ( 1 shl 16)) <> 0;
          26 : Result := ( FShifter and ( 1 shl 17)) <> 0;
          27 : Result := ( FShifter and ( 1 shl 18)) <> 0;
          28 : Result := ( FShifter and ( 1 shl 19)) <> 0;
          29 : Result := ( FShifter and ( 1 shl 20)) <> 0;
          30 : Result := ( FShifter and ( 1 shl 21)) <> 0;
          31 : Result := ( FShifter and ( 1 shl 22)) <> 0;
          32 : Result := ( FShifter and ( 1 shl 23)) <> 0;
          33 : Result := ( FShifter and ( 1 shl 24)) <> 0;
          34 : Result := ( FShifter and ( 1 shl 25)) <> 0;
          35 : Result := ( FShifter and ( 1 shl 26)) <> 0;
          36 : Result := ( FShifter and ( 1 shl 27)) <> 0;
          37 : Result := ( FShifter and ( 1 shl 28)) <> 0;
          38 : Result := ( FShifter and ( 1 shl 29)) <> 0;
          39 : Result := ( FShifter and ( 1 shl 30)) <> 0;
          else Result := False;
        end;
      end;

    var
      Swa   : Boolean;
      Swb   : Boolean;
      Swc   : Boolean;
      Swd   : Boolean;
      Data  : Boolean;
      Trig  : Boolean;
      Reset : Boolean;
    begin
      Reset := SignalToLogic( FInputs[ i_reset]);
      Trig  := SignalToLogic( FInputs[ i_trig ]);

      if ( Reset and not FOldRes) or ResetFlag
      then begin
        ResetFlag := False;
        FCountC1  := 1; FMemoryC1 := False;
        FCountC2  := 2; FMemoryC2 := False;
        FCountC4  := 4; FMemoryC4 := False;
        FCountC8  := 8; FMemoryC8 := False;
        FCountC3  := 3; FMemoryC3 := False;
        FCountC6  := 6; FMemoryC6 := False;
        FShifter  := 0;
      end;

      if Trig and not FOldTrig
      then begin
        Data  :=
          Select( Round( FInputs[ i_selw])) xor
          Select( Round( FInputs[ i_selx])) xor
          Select( Round( FInputs[ i_sely])) xor
          Select( Round( FInputs[ i_selz]));

        DecToZeroWithResetValueToggle( FCountC1, FMemoryC1, 1);
        DecToZeroWithResetValueToggle( FCountC2, FMemoryC2, 2);
        DecToZeroWithResetValueToggle( FCountC4, FMemoryC1, 4);
        DecToZeroWithResetValueToggle( FCountC8, FMemoryC2, 8);
        DecToZeroWithResetValueToggle( FCountC3, FMemoryC1, 3);
        DecToZeroWithResetValueToggle( FCountC6, FMemoryC2, 6);

        FShifter := ( FShifter shl 1) + Cardinal( Ord( not Data));
      end;

      Swa := Select( Round( FInputs[ i_sela]));
      Swb := Select( Round( FInputs[ i_selb]));
      Swc := Select( Round( FInputs[ i_selc]));
      Swd := Select( Round( FInputs[ i_seld]));

      FOutputs[ o_out] := ( Ord( Swa) + 2 * Ord( Swb) + 4 * Ord( Swc) + 8 * Ord( Swd)) / 16.0;

      FOldRes  := Reset;
      FOldTrig := Trig;
    end;


_________________
Jan
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic Moderators: mosc
Page 1 of 1 [3 Posts]
View unread posts
View new posts in the last week
Mark the topic unread :: View previous topic :: View next topic
 Forum index » DIY Hardware and Software » Lunettas - circuits inspired by Stanley Lunetta
Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum
e-m mkii

Please support our site. If you click through and buy from
our affiliate partners, we earn a small commission.


Forum with support of Syndicator RSS
Powered by phpBB © 2001, 2005 phpBB Group
Copyright © 2003 through 2009 by electro-music.com - Conditions Of Use