private void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            // run all background tasks here
            BackgroundWorker worker       = sender as BackgroundWorker;
            DataTable        dtComponents = dsData.Tables["Components"];
            DataView         dv           = new DataView(dtComponents);

            dv.RowFilter = "Pick = 1";
            int currentrow = 0;
            int totalrows  = dv.Count;

            Nozzle1Xoffset = dh.Nozzle1Xoffset;
            Nozzle1Yoffset = dh.Nozzle1Yoffset;
            Nozzle2Xoffset = dh.Nozzle2Xoffset;
            Nozzle2Yoffset = dh.Nozzle2Yoffset;

            if (totalrows > 0)
            {
                /* Components table columns
                 *  ComponentCode
                 *  ComponentName
                 *  PlacementX
                 *  PlacementY
                 *  PlacementRotate
                 *  PlacementNozzle
                 *
                 * component list
                 * ComponentCode
                 * ComponentValue
                 * Package
                 *
                 * PlacementHeight
                 * FeederHeight
                 * FeederX
                 * FeederY
                 * VerifywithCamera
                 * TapeFeeder
                 *
                 *
                 * */
                double pcbHeight = double.Parse(dsData.Tables["BoardInfo"].Rows[0][1].ToString());

                double feedrate   = 20000;
                double feederPosX = 0;
                double feederPosY = 0;
                double feederPosZ = 0;
                double placePosX  = 0;
                double placePosY  = 0;
                //double placePosZ = 0;
                // double placePosA = 0;
                // double placePosRotateZ = 0;
                // double placePosRotateB = 0;
                double ComponentRotation = 0;
                double PlacementHeight   = 0;
                int    PlacementNozzle   = 1;
                bool   TapeFeeder        = false;

                while (currentrow < totalrows)
                {
                    if (backgroundWorkerBuildPCB.CancellationPending)
                    {
                        e.Cancel = true;
                        dv.Dispose();
                        break;
                    }
                    PlacementNozzle = int.Parse(dv[currentrow]["PlacementNozzle"].ToString());


                    feederPosX = CalcXLocation(comp.GetFeederX(dv[currentrow]["ComponentCode"].ToString()), PlacementNozzle);
                    feederPosY = CalcYLocation(comp.GetFeederY(dv[currentrow]["ComponentCode"].ToString()), PlacementNozzle);

                    feederPosZ      = comp.GetFeederHeight(dv[currentrow]["ComponentCode"].ToString());
                    PlacementHeight = comp.GetPlacementHeight(dv[currentrow]["ComponentCode"].ToString()) - pcbHeight;

                    TapeFeeder = comp.GetComponentTapeFeeder(dv[currentrow]["ComponentCode"].ToString());

                    placePosX = CalcXLocation(double.Parse(dv[currentrow]["PlacementX"].ToString()), PlacementNozzle);
                    placePosY = CalcYLocation(double.Parse(dv[currentrow]["PlacementY"].ToString()), PlacementNozzle);

                    ComponentRotation = double.Parse(dv[currentrow]["PlacementRotate"].ToString());


                    PlacementNozzle = int.Parse(dv[currentrow]["PlacementNozzle"].ToString());


                    if (currentrow == 0)
                    {
                        SetFeederOutputs(comp.GetFeederID(dv[currentrow]["ComponentCode"].ToString())); // send feeder to position
                    }



                    kf.MoveSingleFeed(feedrate, feederPosX, feederPosY, ClearHeight, ClearHeight, 0, 0);


                    if (comp.GetComponentTapeFeeder(dv[currentrow]["ComponentCode"].ToString()))
                    {
                        while (!usbController.getFeederReadyStatus())
                        {
                            Thread.Sleep(10);
                        }
                        Thread.Sleep(50);
                        // use picker 1
                        kf.MoveSingleFeed(feedrate, feederPosX, feederPosY, feederPosZ, ClearHeight, 0, 0);
                        Thread.Sleep(200);
                        // go down and turn on suction
                        usbController.setVAC1(true);
                        Thread.Sleep(150);
                        kf.MoveSingleFeed(feedrate, feederPosX, feederPosY, ClearHeight, ClearHeight, 0, 0);
                    }
                    else
                    {
                        // use picker 2
                        while (usbController.CheckChipMotorRunning())
                        {
                            Thread.Sleep(10);
                        }
                        kf.MoveSingleFeed(feedrate, feederPosX, feederPosY, ClearHeight, feederPosZ, 0, 0);
                        Thread.Sleep(200);

                        usbController.setVAC2(true);
                        Thread.Sleep(300);
                        kf.MoveSingleFeed(feedrate, feederPosX, feederPosY, ClearHeight, ClearHeight, 0, 0);
                    }
                    // send picker to pick next item
                    if (currentrow >= 0 && (currentrow + 1) < totalrows)
                    {
                        Thread.Sleep(100);
                        Thread.Sleep(100);


                        SetFeederOutputs(comp.GetFeederID(dv[currentrow + 1]["ComponentCode"].ToString())); // send feeder to position
                    }

                    // rotate head


                    //SetResultsLabelText("Placing Component");
                    if (comp.GetComponentTapeFeeder(dv[currentrow]["ComponentCode"].ToString()))
                    {
                        kf.MoveSingleFeed(feedrate, placePosX, placePosY, ClearHeight, ClearHeight, 0, ComponentRotation);

                        kf.MoveSingleFeed(feedrate, placePosX, placePosY, PlacementHeight, ClearHeight, 0, ComponentRotation);
                        Thread.Sleep(200);
                        usbController.setVAC1(false);
                        Thread.Sleep(50);
                        kf.MoveSingleFeed(feedrate, placePosX, placePosY, ClearHeight, ClearHeight, 0, ComponentRotation);
                    }
                    else
                    {
                        // use picker 2  CalcXwithNeedleSpacing

                        kf.MoveSingleFeed(feedrate, placePosX, placePosY, ClearHeight, ClearHeight, ComponentRotation, 0);
                        Thread.Sleep(200);
                        kf.MoveSingleFeed(feedrate, placePosX, placePosY, ClearHeight, PlacementHeight, ComponentRotation, 0);
                        // go down and turn off suction
                        Thread.Sleep(300);

                        usbController.setVAC2(false);
                        Thread.Sleep(200);
                        kf.MoveSingleFeed(feedrate, placePosX, placePosY, ClearHeight, ClearHeight, ComponentRotation, 0);
                    }

                    currentrow++;
                }
            }
            else
            {
                MessageBox.Show("Board file not loaded");
            }
            backgroundWorkerBuildPCB.CancelAsync();
            usbController.setResetFeeder();
            usbController.RunVibrationMotor(MotorRunLoop);
            kf.RunHomeAll();


            dv.Dispose();
            dtComponents.Dispose();
        }