{"id":24555883,"url":"https://github.com/robcranfill/cpsr16","last_synced_at":"2026-01-02T20:59:21.750Z","repository":{"id":271806672,"uuid":"913585886","full_name":"RobCranfill/cpsr16","owner":"RobCranfill","description":"CircuitPython-based SR16 sorta thing","archived":false,"fork":false,"pushed_at":"2025-02-12T01:49:18.000Z","size":19,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-12T02:40:57.127Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RobCranfill.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-08T01:15:01.000Z","updated_at":"2025-02-12T01:49:22.000Z","dependencies_parsed_at":"2025-01-10T11:47:02.303Z","dependency_job_id":null,"html_url":"https://github.com/RobCranfill/cpsr16","commit_stats":null,"previous_names":["robcranfill/cpsr16"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobCranfill%2Fcpsr16","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobCranfill%2Fcpsr16/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobCranfill%2Fcpsr16/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RobCranfill%2Fcpsr16/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RobCranfill","download_url":"https://codeload.github.com/RobCranfill/cpsr16/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243910713,"owners_count":20367538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-01-23T04:32:59.465Z","updated_at":"2026-01-02T20:59:21.744Z","avatar_url":"https://github.com/RobCranfill.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cpsr16\n\nA CircuitPython-based drum machine, suitable for accompanying live performaces. \n\nUses a 2-button footswitch to advance patterns, select fills, tap tempo.\n\nInspired by the ancient and venerable Alesis SR-16 - hence the name, \u003cb\u003eC\u003c/b\u003eircuit\u003cb\u003eP\u003c/b\u003eython \u003cb\u003eSR-16\u003c/b\u003e.\n\n\n## Features\n * Two-button foot switch: Start/Stop (we will refer to as \"SS\", on left) and Count/Fill (\"CF\", on right).\n   * If DM is stopped, pressing CF more than once sets tempo.\n     ** This just uses the *last two* presses; better would be to average several.\n   * If DM is stopped, pressing SS starts pattern MAIN A.\n   * If DM is playing, pressing SS stops play immediately.\n   * Fill; if DM is playing,\n     * As soon as you press CF, FILL X takes over from MAIN X and plays until the end of the fill *plus the following fill downbeat*.\n       * The \"following downbeat\" is a nice feature of the SR-16; see \"Notes from SR-16 manual\" below.\n     * Normally after playing FILL X, DM will revert back to MAIN X.\n     * If a fill is playing and the CF button is pressed again, after playing FILL X it will transition to MAIN Y.\n  * Display\n    * This is problematic. The Pico doesn't work well with SPI displays - not with what I'm asking of it.\n    * A small I2C OLED display seems to work OK. Adafruit product #4440 (128x32) or #326 (128x64).\n    * A new feature is a NeoPixel 8-LED strip with a \"Christmas tree\" display.\n\n\n## Hardware\n  * Raspberry Pi Pico or similar MCU - https://www.adafruit.com/product/4864\n    * Or upgrade to an RP2350-based MCU!\n    * And/or use a Feather, for battery power!\n  * I2S Stereo decoder like https://www.adafruit.com/product/3678\n  * OLED display: 128 x 64 https://www.adafruit.com/product/326\n  * I2C cable - 6\"-12\"\n    * StemmaQT/Pigtails for Pico https://www.adafruit.com/product/4209\n    * StemmaQT/StemmaQT for Feather https://www.adafruit.com/product/4401\n  * 3 momentary pushbuttons (only 2 used so far!) like https://www.adafruit.com/product/1505\n  * 1/4\" stereo (\"TRS\") jack.\n  * 1/8\" panel-mount stereo extension cable like https://www.adafruit.com/product/3319\n  * 2-unit footswitch like Rowin Beatloop or Boss FS-6.\n  * Some kind of box\n  * USB power cable for MCU\n\n\n## TO DO\n  * Longer measures?\n  * Implement hardware config file?\n  * \"Ready\" beep?\n  * Overall volume control?\n\n## Data file format\nThe input JSON file is basically just an encoding of a Python object.\nIt's a \u003cb\u003elist\u003c/b\u003e of \u003cb\u003edictionaries\u003c/b\u003e, each of which has the following keys:\n\n * \"file comment\": An optional string that will be ignored, for documentation, placed in the first dictionary of the list. (Of course, *any* unknown key will act the same.)\n * \"setup\": The name that will be displayed on the GUI.\n * \"comment\": OIptional doc string.\n * \"bpm\": An integer\n * \"ticks_per_measure\": An integer, usually 16.\n * \"measures_per_pattern\": An integer, usually 1 or 2.\n * \"pads\": A dictionary of \n   * {pad name}: {wav file path}\n * \"patterns\": A dictionary with the keys \"main a\", \"fill a\", \"main b\", \"fill b\",\n    each of which is a dictionary with one or more (zero or more?) keys of\n    {pad name} (where {pad name} was declared in the \"pads\" section), with a key value\n    of a string. The string has ({ticks_per_measure} * {measures_per_pattern}) non-blank characters (blanks are ignored)\n    that are either \"-\", meaning that pad isn't played on that tick, or a digit 0 thru 9, \n    meaning the pad is played at that relative volume. (So \"-\" and \"0\" are equivalent.)\n\n\n\n  \n\n\n\n\n## Hardware Configuration\n\n| Signal   | Pico Pin # | RP2350 Pin # | Device |\n| -------- | -- | -- | ------- |\n| I2C SDA  | 1  | - | Display SDA |\n| I2C SCL  | 2  | - | Display SCL |\n| GND      | 3* | ? | Display GND |\n| AUDIO_OUT_I2S_BIT  | 11 (board.GP8)  | ? |  PCM BCLK |\n| AUDIO_OUT_I2S_WORD | 12 (board.GP9)  | ? |  PCM WSEL |\n| AUDIO_OUT_I2S_DATA | 14 (board.GP10) | ? |  PCM DIN  |\n| GND      | 18* | ? |  PCM GND |\n| BUTTON_B | 21 (board.GP16) | ? | Center menu button |\n| BUTTON_A | 22 (board.GP17) | ? | Left-hand menu button |\n| GND      | 23*             | ? | (all 3 buttons)\n| BUTTON_C | 24 (board.GP18) | ? | Right-hand menu button |\n| GND      | 33* | ? | Footswitch jack SLEEVE |\n| SWITCH_1 | 31 (board.GP28) | ? | Footswitch jack RING |\n| SWITCH_2 | 32 (board.GP27) | ? | Footswitch jack TIP |\n| 3v3      | 36 | ? |  PCM VIN |\n| 3v3      | 36 | - | Display VIN |\n| 3v3      | ?  | D13 | NeoPixel VIN |\n\n\n*Note: GND is GND - use whatever pin you want! For \n\nAlso note: Pico is using \"Adafruit UDA1334 I2S DAC\" board; does not need XXX line tied to ground, as does the Amazon part.\n\n\n## Credits\n* Shout-out to the wonderful Adafruit! \u0026 TodBot \u0026 DanH\n* SR-16 samples from https://www.polynominal.com/sample-packs/Alesis-SR16-sample-pack/\n* Drum patterns from https://drumhelper.com/learning-drums/rock-drum-beats-and-patterns/\n\n\n## Notes\nConvert files to appropriate WAV format (mono, 22050 Hz, 16-bit signed) with command:\n\n\u003ccode\u003e\nsox {original_file}.mp3 -b 16 -c 1 -r 22050 {output_file}.wav\n\u003c/code\u003e\n\n\n## Reference\n### Patterns\n * See https://www.synthmania.com/sr-16.htm\n\n### Notes from SR-16 manual\n*This is not actually what we do, but it was the inspiration.*\n\nThere are 50 of each type of Pattern, numbered 00-49. However, each numbered Pattern\nactually contains four different \"sub-Patterns\":\n\n• A pair of independent Main Patterns (A and B, selected by their respective buttons).\n• A pair of associated Fill Patterns (A Fill and B Fill, selected by pressing the FILL button when\neither A or B is selected). The Fills primarily provide transitional Patterns between Main\nPatterns, which makes for more realistic drum parts. The associated Fill Patterns share the\nsame length, Drum Set, and name as their Main Patterns (e.g., if A is 16 beats, A Fill is 16\nbeats). Otherwise, they are independent.\n\nThe reason for pairing the two different A and B Patterns together is simply so that you can\nswitch back and forth between them rapidly in live performance or while improvising.\nHowever, A and B Patterns can be treated as completely independent Patterns if desired and\ncan have different lengths, Drum Sets, etc.\n\nAlways think of the Main Pattern and its associated Fill as a unit. For example, if you copy a\nMain Pattern to another Main Pattern, its Fill will travel along with it.\nNote that even though there are \"only\" 50 Patterns, the A and B variations double that to 100\nPatterns, and the Fills double that again to 200 Patterns. Added to the Preset Patterns, 400\ntotal Patterns are available.\n\nFill Patterns are the key to creating expressive drum parts. However, Fill is a sophisticated\nfeature that requires some explanation.\n\n...\n\nRemember that Fills are always the same length, and use the same Drum Set, as the\nassociated Main Pattern. This lets you \"drop in\" a Fill at any time. As soon as you press the\nFILL button, the Fill takes over from the Main Pattern and starts playing until the end of the Fill.\n\nGenerally, Fills are transitional Patterns. Example: Suppose an 8-beat A Main Pattern is\nplaying and you press the FILL button on beat 4. The A Fill Pattern will play the last 4 beats\nand then automatically transition into the B Main Pattern. Conversely, if B Main is playing and\nyou press Fill, after B Fill has played, the SR-16 will transition to the A Main Pattern. You can\nselect the Fill at any time the Main Pattern is playing.\n\nHowever, Fills do not have to be transitional Patterns. If you press the FILL button (or\nfootswitch) before the Fill has finished playing and hold it down until after the Fill has played\n(i.e., past the downbeat of the next Pattern), the SR-16 will return to the original Main Pattern.\n\nExample: Suppose an 8-beat A Main Pattern is playing and you press the FILL button on beat\n4 but hold it down past beat 8. The A Fill Pattern will play the last 4 beats, then the SR-16 will\nreturn to the A Main Pattern.\n\nFills cannot start on the downbeat since a Fill, by definition, starts at some point into the Main\nPattern. However, anything you record on the Fill downbeat will play on the first downbeat\nfollowing the Fill (i.e., the downbeat of the next Pattern). To show why this is a useful feature,\nconsider that when coming out of a fill, you'll often want to hit something like a cymbal crash\non the downbeat of the next Pattern yet not have that crash repeat every time the Pattern\nplays. This way of handling Fills lets the downbeat cymbal crash be part of the Fill instead of\nthe Pattern.\n\nBackground \n\nThis way of handling Patterns explains the logic behind having A, B, and Fill Patterns. In typical\npop tunes, A would be the verse and B the chorus. A Fill provides the Fill that transitions from verse\nto chorus, and B Fill provides the Fill that transitions from chorus to verse. Thus, one of the \nnumbered Patterns may be all you need to put together a tune.\n\nThis structure makes it possible to put together songs in minutes using the Preset Patterns. It also\nmakes it easy to play drum parts live. For example, if there's a solo happening over the A Main\nPattern, you can keep the Pattern repeating until the solo is about to end, at which point you\nselect the Fill that leads out of the A Main Pattern.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobcranfill%2Fcpsr16","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobcranfill%2Fcpsr16","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobcranfill%2Fcpsr16/lists"}