/*************************************************************************************
*
* nut-holder-prototype.scad
*
*************************************************************************************
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT
* HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* IT IS NOT PERMITTED TO MODIFY THIS COMMENT BLOCK.
*
* (c)2026, Claude "Tryphon" Theroux, Montreal, Quebec, Canada
* http://www.ctheroux.com/
*
*************************************************************************************/

// Stand tube diameter in mm
NH_StandTubeDiameter = 28.25;

// Tube clearance in mm
NH_TubeClearance = 1;

// Stand tube spacing (center to center) in mm (724)
NH_TubeSpacing = 724;

// Tube holder front length in mm
NH_TubeHolderFrontLength = 100;

// Tube holder back length in mm
NH_TubeHolderBackLength = 140;

// Tube holder thickness in mm.  Minimum 6 mm.
NH_TubeHolderThickness = 7;

module __Customizer_Limit__ () {}

/*************************************************************************************
*
* Nut holder related parameters
*
*************************************************************************************/

// Width in mm
NH_Width = 33.5;

// Thickness in mm ????????????
NH_Thickness = 4.6;

// Bottom depth in mm
NH_BottomDepth = 30;

// Top depth in mm
NH_TopDepth = 28;

// Screw head diameter in mm
NH_ScrewHeadDiameter = 12;

// Screw head thickness in mm
NH_ScrewHeadThickness = 4.5;

// Screw hole diameter in mm
NH_ScrewHole = 6.5;

// Screw spacing on the keyboard (center to center) in mm (712)
NH_ScrewSpacing = 712;

// Width of the holder outside the tube holder in mm
NH_ExtraOutsideHolderWidth = 60;

/*************************************************************************************
*
* Zip tie holder related parameters
*
*************************************************************************************/

// Spacing of the Zip Tie from the top of the holder in mm
NH_ZipTieSpacing = 2.5;

// Zip Tie hole width in mm
NH_ZipTieHomeWidth = 6;

// Zip Tie hole height in mm
NH_ZipTieHoleHeight = 3;

/*************************************************************************************
*
* Miscellaneous parameters
*
*************************************************************************************/

// Spacing between the object in mm
NH_ObjectSpacing = 10;

YKB_Debug = true;

/*************************************************************************************
*
* Nothing shall be modified below this line
*
*************************************************************************************/

$fn = 60;

// Delta between NH_ScrewSpacing and NH_TubeSpacing.  Negative means that the tube are inside de screws on the keyboard.
YKB_SpacingDelta = NH_TubeSpacing - NH_ScrewSpacing;

// Width of the holder base
YKB_HolderBaseWidth = NH_StandTubeDiameter + NH_TubeClearance + 2 * NH_TubeHolderThickness;

// Total lenght of the holder. 
YKB_TotalLength = NH_TubeHolderFrontLength + NH_TubeHolderBackLength;

module YKB_Dump(p_EnableDebug = false) {
    if( p_EnableDebug ) {
        echo("vvv YKB_Dump");
        echo("    YKB_SpacingDelta:", YKB_SpacingDelta);
        echo("    YKB_HolderBaseWidth:", YKB_HolderBaseWidth);
        echo("    YKB_TotalLength:", YKB_TotalLength);
        echo("^^^ YKB_Dump");
    }
}

module LeftNutHolder() {
    difference() {
        translate( [ 0, 0, 0 ] ) rotate( [ 90, 0, 90 ] ) linear_extrude(NH_Width) polygon([ [ 0, 0 ], [   NH_BottomDepth, 0 ], [ NH_BottomDepth - (NH_BottomDepth - NH_TopDepth) / 2, NH_Thickness ], [ (NH_BottomDepth   - NH_TopDepth) / 2, NH_Thickness ]  ]);
        translate( [ NH_Width - 15, 16.25, 0 ] ) cylinder(d = NH_ScrewHole, h = NH_Thickness);
        translate( [ 0, 0 ,0 ] ) cube( [ 5.5, 11.5, NH_Thickness ] );
    }
}

module RightNutHolder() {
    difference() {
        translate( [ 0, 0, 0 ] ) rotate( [ 90, 0, 90 ] ) linear_extrude(NH_Width) polygon([ [ 0, 0 ], [   NH_BottomDepth, 0 ], [ NH_BottomDepth - (NH_BottomDepth - NH_TopDepth) / 2, NH_Thickness ], [ (NH_BottomDepth   - NH_TopDepth) / 2, NH_Thickness ]  ]);
        translate( [ 15, 16.25, 0 ] ) cylinder(d = NH_ScrewHole, h = NH_Thickness);
        translate( [ NH_Width - 5.5, 0 ,0 ] ) cube( [ 5.5, 11.5, NH_Thickness ] );
    }
}

module YKB_ScrewKnockoff() {
    cylinder(h = NH_TubeHolderThickness - NH_ScrewHeadThickness, d = NH_ScrewHole);
    translate( [ 0, 0, NH_TubeHolderThickness - NH_ScrewHeadThickness ] ) cylinder(h = NH_TubeHolderThickness + NH_StandTubeDiameter / 2, d = NH_ScrewHeadDiameter);
}

module ZipTieHole(p_Y) {
    translate( [ 0, p_Y, NH_ZipTieSpacing ] ) cube( [ YKB_HolderBaseWidth + abs(YKB_SpacingDelta) / 2, NH_ZipTieHomeWidth, NH_ZipTieHoleHeight ]);
}

module YKB_TubeHolder() {
    holderOffset = ( YKB_SpacingDelta < 0 ? abs(YKB_SpacingDelta / 2) : 0 );
    holderOutsideOffset = ( YKB_SpacingDelta > 0 ? YKB_HolderBaseWidth : 0 );
    
    difference() {
        union() {
            translate( [ holderOffset, 0, 0 ] ) cube([ YKB_HolderBaseWidth, YKB_TotalLength, NH_TubeHolderThickness ]);
            translate( [ holderOutsideOffset, NH_TubeHolderFrontLength - NH_ExtraOutsideHolderWidth / 2, 0 ] ) cube([ abs(YKB_SpacingDelta / 2), NH_ExtraOutsideHolderWidth, NH_TubeHolderThickness ]);
            translate( [ holderOffset, 0, NH_TubeHolderThickness ] ) difference() {
                cube([ YKB_HolderBaseWidth, YKB_TotalLength, (NH_StandTubeDiameter + NH_TubeClearance) / 2 ]);
                translate( [ (NH_StandTubeDiameter + NH_TubeClearance) / 2 + NH_TubeHolderThickness, 0, (NH_StandTubeDiameter + NH_TubeClearance) / 2 ] ) rotate([ -90, 0, 0 ]) cylinder(h = NH_TubeHolderFrontLength + NH_TubeHolderBackLength, d = NH_StandTubeDiameter + NH_TubeClearance);
            }  
        }
        translate( [  abs(YKB_SpacingDelta) / 2 + YKB_HolderBaseWidth / 2 - holderOffset, NH_TubeHolderFrontLength, 0 ] ) YKB_ScrewKnockoff();
        for( y = [ NH_TubeHolderFrontLength - NH_ExtraOutsideHolderWidth / 2 - 10 : -20 : NH_ZipTieHomeWidth + 2 ] ) {
            ZipTieHole(y);
        }
        for( y = [ NH_TubeHolderFrontLength + NH_ExtraOutsideHolderWidth / 2 + 10 : 20 : YKB_TotalLength -NH_ZipTieHomeWidth - 2 ] ) {
            ZipTieHole(y);
        }
    }
}

module YKB_RightTubeHolder() {
    YKB_TubeHolder();
}

module YKB_LeftTubeHolder() {
    translate( [ YKB_HolderBaseWidth + abs(YKB_SpacingDelta) / 2, 0, 0 ] ) mirror( [ 1, 0, 0 ] ) YKB_TubeHolder();
}

YKB_Dump(YKB_Debug);

ObjectOffset = YKB_HolderBaseWidth + NH_ObjectSpacing + abs(YKB_SpacingDelta / 2);

YKB_LeftTubeHolder();
translate( [ ObjectOffset, 0, 0 ] ) YKB_RightTubeHolder();
translate( [ ObjectOffset * 2, 0, 0 ] ) RightNutHolder();
translate( [ ObjectOffset * 2, NH_BottomDepth + NH_ObjectSpacing, 0 ] ) LeftNutHolder();


