Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GEMINI_API_KEY=YOUR_API_KEY_HERE
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
venv/
134 changes: 133 additions & 1 deletion Python UI/Pico_crosspoint-xp3a-mini-rpi-red.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@
#
from tkinter import scrolledtext
#
try:
import google.generativeai as genai
from dotenv import load_dotenv
import os
load_dotenv()
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
genai.configure(api_key=GEMINI_API_KEY)
GeminiModel = genai.GenerativeModel("gemini-3.1-flash-lite-preview")
except:
showwarning("WARNING","google-generativeai or python-dotenv not installed? Run: pip install google-generativeai python-dotenv")
#
# adjust for your specific hardware by changing these values in the alice.init file
ADC_Cal = 3.25
VOpenCircuit = 2.4
Expand Down Expand Up @@ -1644,6 +1655,9 @@ def MakeBreadboardScreen():
global CompSpinBoxList_RC, CompSpinBoxList_TL, CompSpinBoxList_BL, CompSpinBoxList_TR, CompSpinBoxList_BR
global click_loc, breadboard_image, JPcolors, breadboard_canvas

style = Style() # This accesses the ttk Style object
style.configure("Prompt.TEntry", fieldbackground="white", foreground="black")

if BreadboardStatus.get() == 0:
try:
XlabLogo_image = PhotoImage(file='./XLab-logo.png') #
Expand Down Expand Up @@ -1826,10 +1840,80 @@ def MakeBreadboardScreen():
VerifyButton.grid(row=20, column=0, columnspan=2, sticky=W, pady=1)
PassFailSvBB = Label(matrixwindow,text="")
PassFailSvBB.grid(row=20, column=2, columnspan=4, sticky=W, pady=1)



if HWRevOne == "Red3":
TestResButton = Button(matrixwindow, text="Man Test Resistor", style="W17.TButton", command=MakeTestResWindow)
TestResButton.grid(row=21, column=0, columnspan=2, sticky=W, pady=1)


# --- PROMPT BOX ---
# --- CLASSIC TK SETUP ---
import tkinter as tk_base # Ensure we have access to classic widgets

# 1. CREATE STYLE FOR CURSOR
# This fixes the cursor color for the ttk Entry
style = Style()
style.configure("Prompt.TEntry",
fieldbackground="white",
foreground="black",
insertcolor="black", # <--- FIXES VISIBLE CURSOR
insertwidth=2)

# 2. CREATE DRAGGABLE PANED WINDOW
# This allows you to drag the divider up/down to resize the chat
chat_paner = tk_base.PanedWindow(matrixwindow,
orient=tk_base.VERTICAL,
sashwidth=6,
sashrelief=tk_base.RAISED,
bg=FrameBG)
chat_paner.grid(row=22, column=0, columnspan=4, sticky="nsew", padx=5, pady=10)

# Give row 22 all the weight so it fills the bottom area
matrixwindow.rowconfigure(22, weight=1)

# 3. CHAT HISTORY (Top Pane)
global ChatHistory
ChatHistory = scrolledtext.ScrolledText(
chat_paner, # Parent is the paner
height=10,
state='disabled',
wrap='word',
bg="white",
foreground="black",
insertbackground="black",
font=("Arial", 10)
)

# Add to paned window
chat_paner.add(ChatHistory, minsize=100)

# 4. PROMPT INPUT AREA (Bottom Pane)
# We use a frame to hold the Label and Entry together in the bottom pane
input_container = tk_base.Frame(chat_paner, bg=FrameBG)

PromptLabel = Label(input_container, text="User Prompt:", style="A12B.TLabel")
PromptLabel.pack(side=tk_base.TOP, anchor=tk_base.W, pady=(5, 0))

global PromptBox
# Using Style "Prompt.TEntry" defined above
PromptBox = Entry(input_container, style="Prompt.TEntry")
PromptBox.pack(side=tk_base.TOP, fill=tk_base.X, pady=(0, 10))

# Add frame to paned window
chat_paner.add(input_container, minsize=80)

# 5. CONFIGURE TAGS
ChatHistory.tag_configure("user_tag", foreground="#0078d4", font=("Arial", 10, "bold"))
ChatHistory.tag_configure("ai_tag", foreground="#2b88d8", font=("Arial", 10, "bold"))
ChatHistory.tag_configure("text_tag", foreground="black", font=("Arial", 10))
ChatHistory.tag_configure("status_tag", foreground="gray", font=("Arial", 10, "italic"))

# 6. BINDINGS & FOCUS
PromptBox.bind("<Return>", handle_user_prompt)
PromptBox.focus_set()


##############################
### MIDDLE SIDE OF SCREEN ####
#### The top part of the middle section is the simulated image of the breadboard
Expand Down Expand Up @@ -1877,6 +1961,9 @@ def MakeBreadboardScreen():
J_Connections_Labels.append(J_connections)

##############################

# Add this at the end of the function to set focus on startup
PromptBox.focus_set()
#
def BBCAresize(event):
global breadboard_canvas, BBwidth, BBheight, CANVASwidthBB, CANVASheightBB
Expand Down Expand Up @@ -7708,4 +7795,49 @@ def onResSchClick(event):
SendByt = SendStr.encode('utf-8')
ser.write(SendByt)
#

# create an AI prompt box
def handle_user_prompt(event):
global PromptBox, ChatHistory
user_input = PromptBox.get().strip()

def handle_user_prompt(event):
global PromptBox, ChatHistory, GeminiModel
user_input = PromptBox.get().strip()

if not user_input:
return

# 1. Clear input immediately
PromptBox.delete(0, END)

# 2. Enable box for appending
ChatHistory.config(state=NORMAL)

# 3. Add User Prompt with Tag
ChatHistory.insert(END, "\nYou: ", "user_tag")
ChatHistory.insert(END, f"{user_input}\n", "text_tag")

# 4. "Thinking" Indicator
ChatHistory.insert(END, "AI: Thinking...\n", "status_tag")
ChatHistory.see(END)
ChatHistory.update()

# 5. Get Gemini Response
try:
response = GeminiModel.generate_content(user_input)
reply = response.text
except Exception as e:
reply = f"Error: {str(e)}"

# 6. Replace "Thinking..." with the actual response
ChatHistory.delete("end-2l", "end-1c")
ChatHistory.insert(END, "AI: ", "ai_tag")
ChatHistory.insert(END, f"{reply}\n", "text_tag")

# 7. Finalize view
ChatHistory.see(END)
ChatHistory.config(state=DISABLED)

# ENSURE CURSOR STAYS IN BOX
PromptBox.focus_set()